假设我有一个包含X
项的线程池,并且给定的任务使用了Y
这些项目(其中Y
远小于X
)。< / p>
我想等待给定任务的所有线程(Y
项)完成,而不是整个线程池。
如果线程池的execute()
方法返回了对所用线程的引用,我可以join()
对这些Y
个线程中的每一个进行简化,但事实并非如此。
有谁知道一种优雅的方法来实现这一目标?感谢。
答案 0 :(得分:3)
而不是execute()
Runnable
s,而只是invokeAll()
一些Callable
s - 然后您可以为每个Future
获得get()
{{1}} {{1}} 1}},阻止任务完成。
答案 1 :(得分:3)
您可以使用CyclicBarrier并让每个线程仅在类型为Y时等待。例如。
ExecutorService executor = Executors.newFixedThreadPool(X.size);
public void executeAllAndAwaitCompletion(List<? extends Y> myRunnableY){
final CyclicBarrier barrier = new CyclicBarrier(myRunnable.size()+1);
for(final Y y : myRunnableY){
executor.submit(new Runnable(){
public void run(){
y.run();//for the sake of this example y has a run method
barrier.await();
}
});
}
barrier.await();
}
因此,运行类型Y的每个线程都将等到所有这些Y完成。请注意,您必须在屏障大小上添加1以说明最初正在执行的线程也要等待。
另请注意:如果Michael Borgwardt的例子适合您,那将是最好的。但是,如果您需要线程池,对于运行Y的每个线程,如果不运行任何其他非Y,则我的解决方案将是您可以执行此操作的唯一方法。 Future.get()只会阻塞调用线程,当线程池完成Y的执行时,它将接收其他一些(可能是非Y)任务。
答案 2 :(得分:2)
您应该使用CompletionService
来实现此目的。
Executor
ExecutorCompletionService
CompletionService
take
或poll
等待任务完成您可以与其他人共享Executor,只需在顶部创建CompletionService
并将其用于特定任务。
答案 3 :(得分:0)
使用CountDownLatch
作为计数创建Y
,并在每个latch.countDown()
任务中执行Y
。最后latch.await()
将确保完成所有Y
任务。