【问题标题】:Reliably write from multiple threads to one PrintWriter可靠地从多个线程写入到一个 PrintWriter
【发布时间】:2011-12-08 02:47:25
【问题描述】:

我遇到了一个问题,我有多个线程写入同一个 PrintWriter,但并非所有数据都写入文件。我知道多线程部分工作正常,因为我可以将所有内容打印到控制台。同步写入语句似乎不起作用。可能是什么问题?

ExecutorService pool = Executors.newFixedThreadPool(poolSize);

for (Integer i : map.keySet()) {
    final Collection<String[]> set = map.get(i);
    pool.submit(new Runnable() {
        public void run() {
        StringBuffer sb = Matcher.performCollectionMatch(params);
        synchronized (this) {
            resultFile.print(sb); //this is a PrintWriter - it does NOT capture all sb
            resultFile.flush();
            System.out.print(sb); //this actually prints out ALL sb
        }
        }
    });
} //FOR loop

【问题讨论】:

  • 你的池子够大吗?
  • 我认为是。我将它设置为 10 个线程,并且没有耗尽内存。另外,我知道线程工作正常,因为我可以捕获 System.out 的输出并且它是准确的。

标签: java multithreading file-io io


【解决方案1】:

为了使同步工作,您应该为所有线程使用相同的对象,例如:

...
synchronized (resultFile) {
...

【讨论】:

  • 最初这正是我所尝试的(我对同步语句的理解)。但是,它向文件中写入的结果更少。
  • 那么其他事情就大错特错了。这个答案正确地修复了这里的同步,这实际上并没有保护对流的访问。
【解决方案2】:

池停止后你会关闭PrintWriter吗?

pool.shutdown();
final boolean terminated = pool.awaitTermination(8, TimeUnit.SECONDS);
if (!terminated) {
    throw new IllegalStateException("pool shutdown timeout");
}

resultFile.close();

【讨论】:

  • 我没有意识到 pool.shutdown() 在所有线程都完成之前不会阻塞。简单修复:`pool.shutdown(); while (!pool.isTerminated) { } resultFile.close(); `
  • 这个while 使用了大量的CPU。 awaitTermination 做同样的事情,但使用 0% 的 CPU。
  • 感谢您的提示。会做相应的修改。
【解决方案3】:

一个更简单的解决方案是确保池中只有一个线程。这样你就不需要同步写入,因为只有一个线程。

ExecutorService pool = Executors.newSingleThreadedPool();

for (Integer i : map.keySet()) {
    final Collection<String[]> set = map.get(i);
    pool.executor(new Runnable() {
        public void run() {
            StringBuilder sb = Matcher.performCollectionMatch(params);
            resultFile.print(sb); //this is a PrintWriter - it does NOT capture all sb 
            System.out.print(sb); //this actually prints out ALL sb
        }
    });
} //FOR loop

瓶颈很可能是您的磁盘访问,因此添加更多线程可能无济于事。

【讨论】:

  • @kirdie 恕我直言,多线程的目的是最大化性能,而不是使用我拥有的所有内核。通常,最佳线程数是 1。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多