2011-10-14 21 views
0

我遇到了一个问题,其中有多个线程写入同一个PrintWriter,而并非所有数据都写入该文件。我知道多线程部分工作正常,因为我可以将所有内容打印到控制台。同步写入语句似乎不起作用。可能是什么问题呢?可靠地从多个线程写入一个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 
+0

你的泳池尺寸够大吗? –

+0

我认为是。我将它设置为10个线程,并且没有耗尽内存。另外,我知道这些线程正在正确地完成工作,因为我可以捕获System.out的输出并且它是准确的。 – banncee

回答

3

你关闭PrintWriter池停止后?

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

resultFile.close(); 
+0

我没有意识到的是,pool.shutdown()不会阻塞,直到所有线程完成。简单修复: ' pool.shutdown(); (!pool.isTerminated) resultFile.close(); ' – banncee

+2

这''while'使用了很多CPU。 'awaitTermination'也是一样的,但是使用0%的CPU。 – palacsint

+1

感谢您的提示。将相应修改。 – banncee

4

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

... 
synchronized (resultFile) { 
... 
+0

最初,这正是我所尝试的(我对synchronized语句的理解)。但是,该文件的结果甚至更少。 – banncee

+1

其他的东西是相当错误的。这个答案在这里正确地修复了同步,这实际上并不保护对流的访问。 –

1

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

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 

瓶颈很可能是磁盘访问,所以添加更多的线程可能没有帮助。

+0

但是这打破了多线程的目的:-) –

+0

@kirdie恕我直言,多线程的目的是最大限度地提高性能,而不是使用我拥有的所有内核。通常最佳的线程数是1。 ;) –

相关问题