我觉得我的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中的最后一个任务运行时,线程“冻结”,就像它正在等待其他事情完成一样。
怎么了?
答案 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; (可用于获取特定作业状态的句柄) - 执行程序本身在您关闭之前不会终止。想象一下像'批处理队列'或'协处理器'这样的遗嘱执行人等着你在漏斗中投入一些工作。
更新:格雷比我更好地回答 - 看他的帖子。 - (人们如何快速键入?)