2011-01-08 109 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任務都完成。