下面的代码演示了如何使用 Executor 周围的包装类来计算已提交作业的数量,并将其与已完成作业的数量进行比较,以实现您想要的效果 . 请注意,您的任务必须调用包装类的 execute 方法,并且永远不要直接调用底层的 Executor . 如果需要,扩展下面的包装器以包装'submit'的'submit'方法应该是微不足道的 .
public class ExampleExecutor {
private final Executor executor;
private long submitCount = 0;
private long doneCount = 0;
public ExampleExecutor(Executor executor) {
this.executor = executor;
}
public synchronized void execute(Collection commands) {
for (Runnable command : commands) {
execute(command);
}
}
public synchronized void execute(final Runnable command) {
submitCount ++;
executor.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
synchronized (ExampleExecutor.this) {
doneCount++;
if (doneCount == submitCount) {
ExampleExecutor.this.notifyAll();
}
}
}
}
});
}
public synchronized void awaitCompletion() throws InterruptedException {
while (doneCount != submitCount) {
this.wait();
}
}
}
EDIT :在下面添加了测试用例,以演示如何使用上述代码
public class Test {
static class Task implements Runnable {
private final String id;
private final long repetitions;
private final long respawnSize;
private final ExampleExecutor executor;
public Task(String id, long repetitions, long respawnSize, ExampleExecutor executor) {
this.id = id;
this.repetitions = repetitions;
this.respawnSize = respawnSize;
this.executor = executor;
}
public void run() {
for (int i = 0; i < respawnSize; i ++) {
// Spawning new sub tasks
executor.execute(new Task(id + "-" + i, repetitions/2, 0, null));
}
double sum = 0;
for (int i = 0; i < repetitions; i++) {
sum += Math.sin(i);
}
System.err.println(id + " completed at " + System.currentTimeMillis() + " with sum=" + sum);
}
}
public static void main(String argv[]) throws InterruptedException {
ExampleExecutor executor = new ExampleExecutor(Executors.newFixedThreadPool(2));
executor.execute(new Task("0", 2000000, 100, executor));
System.err.println("main thread awaits completion");
executor.awaitCompletion();
System.err.println("main thread recieved completion event");
}
}