我使用相同的线程池完成了一系列不同的“任务”。我想测量执行每项任务所需的时间,但为此我需要等待“任务”中的每项任务(抱歉模棱两可)才能完成。
如果只有一项任务,我通常会这样做:
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
并等待所有任务完成?
答案 0 :(得分:2)
您可以等待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();
答案 1 :(得分:2)
使用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。这样,您确定只有在完成处理当前批次后才能将任务重新提交给执行者
答案 2 :(得分:0)
您可以创建一个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");