线程池不接受新任务

时间:2014-01-13 21:10:03

标签: java multithreading concurrency

我觉得我的java并发知识正在变得生疏,我试图弄清楚为什么线程池不接受以下代码中的更多任务:

ExecutorService e = Executors.newFixedThreadPool(aNumber);

// Task 1
for (int i=0; i<n; i++)
    e.submit(new aRunnable());
while (!e.isTerminated());
System.out.println("Task 1 done");

// Task 2
for (int i=0; i<n; i++)
    e.submit(new anotherRunnable());
while (!e.isTerminated());
System.out.println("Task 2 done");

它永远不会启动任务2,当任务1中的最后一个任务运行时,线程“冻结”,就像它正在等待其他事情完成一样。

怎么了?

2 个答案:

答案 0 :(得分:4)

  

它永远不会启动任务2,当任务1中的最后一个任务运行时,线程“冻结”,就像它正在等待其他事情完成一样。

正在等待。 ExecutorService.isTerminated()在池关闭后等待线程池任务完成。既然你从未打过e.shutdown();,你的循环就会永远旋转。引用ExecutorService javadocs

  

如果关闭后所有任务都已完成,则返回true。请注意,除非先调用shutdown或shutdownNow,否则isTerminated永远不会为真。

你没有关闭服务,所以永远不会是真的。一般来说,任何像while循环一样旋转的东西都是非常糟糕的模式。通常情况下,我们会使用e.awaitTermination(...),但这只是在您调用e.shutdown();之后。并且你不想关闭ExecutorService,因为你将要向它提交更多任务。

如果您想等待所有任务完成,请提交更多任务,我会执行以下操作,并在第一批返回的get()上调用Future提交任务。类似的东西:

List<Future> futures = new ArrayList<Future>();
for (int i=0; i<n; i++) {
    futures.add(e.submit(new aRunnable()));
}
// now go back and wait for all of those tasks to finish
for (Future future : futures) {
    future.get();
}
// now you can go forward and submit other tasks to the thread-pool

答案 1 :(得分:0)

如果您想知道特定任务何时完成,请使用ExecutorService,它将返回Future&lt;&gt; (可用于获取特定作业状态的句柄) - 执行程序本身在您关闭之前不会终止。想象一下像'批处理队列'或'协处理器'这样的遗嘱执行人等着你在漏斗中投入一些工作。

更新:格雷比我更好地回答 - 看他的帖子。 - (人们如何快速键入?)