我正在使用Java执行器来并行划分和处理给定任务。可以有任意数量的任务。它们都在开头排队,主控制器对象只是等待所有它们完成。
我遇到的问题是如何确定所有任务何时完成。由于一个大任务只在一次排队(即所有当前排队的任务都属于同一个主任务),我可以使用getCompletedTaskCount()
方法将已完成任务的数量与数量的最初排队的任务。
然而,这要求我不断地向执行人员查询已完成任务的数量,而且我认为这不是一个很好的解决方案。
while (pool.getCompletedTaskCount() - start_count < num_tasks)
{
try
{
Thread.sleep(30);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我想过有一个计数器对象,每个任务都可以递增,然后如果计数等于预期任务的数量通知主线程。像这样的东西(忽略一些不完整的代码,比如缺少异常处理程序等):
主线程:
counter_object.expected_count = num_tasks;
counter_object.count = 0;
queue_tasks();
synchronized(counter_object)
{
counter_object.wait();
}
// all tasks have finished
工作人员任务:
// ...do task
// task finished, update counter
synchronized(counter_object)
{
++counter_object.count;
if(counter_object.count == counter_object.expected_count)
{
// all tasks have finished, notify master thread
counter_object.notify();
}
}
此方法还有一个额外的好处,即我可以使用单个执行程序来运行多个主任务,因为计数器对象对于给定的主服务器是本地的。
有没有更好的方法来解决这个问题?任务的数量可能大于允许执行者创建的最大线程数,因此我认为CyclicBarrier不会起作用。
答案 0 :(得分:2)
这听起来像是ExecutorService.invokeAll的作品。
Collection<Callable> tasks = <get all sub tasks>;
executorService.invokeAll(tasks);
// Execution proceeds at the following line only once all "tasks" have been run
或者(因为您可能正在处理Runnable
个实例,而不是Callable
,您可以使用ExecutorService.submit(Runnable)
然后等待它们完成。
for (Runnable task:tasks) {
futures.add(executorService.submit(task));
}
for (Future<Void> result:futures) {
result.get();
}
注意:省略了异常处理