2011-01-08 120 views
1

比方说,我有一个线程池包含X项目,并且给定的任务使用这些项目的Y(其中Y远小于X)。等待Java线程池中的线程子集

我想等待给定任务的所有线程(Y项)完成,而不是整个线程池。

如果线程池的​​方法返回对聘用线程的引用,我可以简单地将join()分配给这些Y线程中的每一个线程,但事实并非如此。

有没有人知道一个优雅的方式来实现这一目标?谢谢。

回答

3

而不是​​荷兰国际集团Runnable S,只是invokeAll()一些Callable秒 - 那么你得到的每个上,您可以拨打get(),该块,直到任务完成了Future

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)任务。

+0

这真的很酷 - 谢谢 - 但所有的任务是相同的类型(他们只属于不同的父母)。 – 2011-01-08 18:37:51

2

您应该使用一个CompletionService这是完全用于此目的。

  • 创建Executor
  • 使用执行人
  • 对下,CompletionService通过CompletionService
  • 使用takepoll提交任务等待任务完成
  • 重复,直到所有的任务创建ExecutorCompletionService你提交已完成
  • 完成

您可以与其他人共享Executor,只需在顶部创建CompletionService并将其用于您的特定任务。

0

创建CountDownLatchY作为计数,并在Y任务中做latch.countDown()。最后latch.await()将确保所有的Y任务都完成。