我正在使用ExecutorCompletionService在完成执行后立即获取作业的结果。伪代码是这样的——
Instantiate FixedThreadPool executor, exec
Instantiate ExecutorCompletionService, completionService
for(taskList) {
completionService.submit(someTask)
}
exec.shutDown();
whie(!exec.isShutdown()) { //Line 1
Task t = completionService.take(); //Line 2
}
众所周知,shutdown()
等待所有提交任务的完成,所以只要有一个任务正在进行中,而 Line1 上的条件返回 true,并且代码进入循环以从队列中取出已完成的任务并在必要时等待。
现在,我观察到上述代码存在一个问题,即即使没有更多的任务正在进行,所有任务都已完成,控制也会在第 2 行被阻止。
我认为这是因为当最后一个任务完成并添加到完成队列时,ThreadPoolExecutor
恢复关闭过程,因为没有更多待处理的提交任务。但是,当它仍在关闭时,下一次迭代发生了,isShutdown()
返回 false,因此它进入循环并被take()
调用阻止,即使没有更多任务。所以也许是最后一次take
呼叫和游泳池正确关闭之间的时间。我的想法是否正确?
所以我在想这是否是使用并从完成服务中获得结果的正确方法? 为了解决这个问题,我可以将 line1 上的while
替换为for(taskList)
以避免isShutdown
调用。 还有一件事,最佳做法是关闭执行器,然后从 completionservice 获取结果,还是先收集结果并最终关闭 execturo?
尝试使用isTerminated()而不是 isShutoown()。但最好的选择是使用awaitTermination()方法而不是创建此循环。