[英]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.