簡體   English   中英

等待所有任務完成

[英]Waiting for all the tasks to finish

我有一系列使用相同線程池完成的不同“任務”。 我想測量執行每項任務所需的時間,但為此我需要等待“任務”中的每項任務(抱歉模棱兩可)才能完成。

當我只做一個任務時,我通常會這樣做:

ExecutorService e = Executors.newCachedThreadPool();
for (int i=0; i<100; ++i)
    e.submit(target);
e.shutdown();
while (!e.isTerminated());

但由於將有幾個任務提交到池中,我無法拒絕。 所有與等待任務完成提及“關閉請求后”相關的方法。 好吧,如果我不想關閉它,但等待所有線程完成然后提交更多任務怎么辦?

這就是我想要做的:

ExecutorService e = Executors.newCachedThreadPool();
for (int i=0; i<100; ++i)
    e.submit(target);
// wait for all targets to finish
for (int i=0; i<100; ++i)
    e.submit(target); // submit different tasks
// wait... and so on

我想過關閉池然后再使用prestartAllCoreThreads “喚醒它”,但后來我意識到這不是ExecutorService方法而是ThreadPoolExecutor方法。 這可能是一個解決方案嗎? 關閉它,等待,然后再次激活池? 對我來說似乎有點難看。

我還認為最自然的事情是使用CyclicBarrier ,但這似乎是一種特定的方式,而我認為能夠使用任何ExecutorService進行我正在嘗試的事情是最合乎邏輯的事情。去做。

有什么方法可以堅持ExecutorService並等待所有任務完成?

您可以等待該ExecutorService的終止。

    ExecutorService executor = Executors.newCachedThreadPool();    
   //do your stuff

    try {
        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.MINUTES);
    } catch (InterruptedException e) {
        //handle
    }

或者使用CountDownLatch

CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}

try {
  latch.await();
} catch (InterruptedException E) {
   // handle
}

並在你的任務中(包含在try / finally中)

latch.countDown();

使用CyclicBarrier進行所需的工作,如下所示:

// the optionalRunnable can collect the data gathered by the tasks
CyclicBarrier b = new CyclicBarrier(numberOfTasks,optionalRunnable)

Task yourTaks = new Task(...., b);
// inside the run method call b.await() after the work is done;
executor.submit(yourTaks);

或者,您也可以在主線程中調用await並將屏障實例化為numTasks + 1。 這樣,只有在完成當前批處理后,您才能確保將任務重新提交給執行程序

您可以創建一個TaskListener接口,並將其傳遞給每個任務。 每個任務在啟動和停止時通知TaskListener。 然后,您可以創建一個TimingTaskListener實現,該實現維護一個可以在以后查詢的持續時間的ConcurrentMap。

public interface TaskListener {
   void onStart(String taskId);
   void onEnd(String taskId);
}

public class Task implements Runnable {
   private TaskListener taskListener;
   private String taskId;

   public Task(String taskId, TaskListener taskListener) {
      this.taskId = taskId;
      this.listener = listener;
   }

   public void run() {
      listner.onStart(taskId);
      try {
         doStuff();
      } finally {
         listener.onEnd(taskId);
      }
   }
}

// TODO: Implement TimingTaskListener to save durations to a ConcurrentMap
TimingTaskListener timingListener = new TimingTaskListener(); 
Runnable task1 = new Task("task1", timingListener);
Runnable task2 = new Task("task2", timingListener);

Future<?> f1 = e.submit(task1);
Future<?> f2 = e.submit(task2);

// futures block until the task is finished.
// You could also use a CountDownLatch to achieve the same
f1.get();
f2.get();

long time1 = timingListener.getDuration("task1");
long time2 = timingListener.getDuration("task2");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM