线程池不接受新任务



我觉得我的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,线程"冻结";当任务1中的最后一个任务运行时,就像在等待其他任务完成一样。

它正在等待。ExecutorService.isTerminated()在线程池关闭后等待线程池任务完成。由于您从未调用过e.shutdown();,因此循环将永远旋转。引用ExecutorServicejavadocs:

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

您没有关闭服务,所以这永远不会是真的。一般来说,在while循环中旋转的任何东西都是反模式——至少在循环中放入一个Thread.sleep(10);。通常我们使用e.awaitTermination(...),但同样,这只是在您调用e.shutdown();之后。你不想关闭ExecutorService,因为你将向它提交更多的任务。

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

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

如果您想知道特定任务何时完成,请使用ExecutorService,它将返回Future<>(一个可以用来获取特定作业状态的句柄)--执行器本身在关闭它之前不会终止。想象一下像"批处理队列"或"协处理器"这样的执行器在等待您将一些工作放入料斗。

更新:格雷的回答比我好得多——看他的帖子。——(人们怎么打字那么快??)

最新更新