假设我在一个程序中有多个 Runnable 实例,全部由一个 Executor 实例调度。此外,假设我在某些时候需要等待这些可运行文件的一个子集完成,然后再继续。
我可以这样做的一种方法是:
public abstract class Joinable implements Runnable {
private final Semaphore finishedLock = new Semaphore(1);
@Override
public final void run() {
try {
finishedLock.acquireUninterruptibly();
doWork();
} finally {
finishedLock.release();
}
}
public abstract void doWork();
public void join() {
finishedLock.acquireUninterruptibly();
}
}
然后实现类可以简单地覆盖 doWork(),而不是 run(),以便定义在执行期间应该做什么。
加入过程将如下所示:
void doStuff() {
Executor executor = Executors.newCachedThreadPool();
List<Joinable> joinables = new LinkedList<Joinable>();
// Fill joinables with implementors of Joinable...
List<Runnable> others = new LinkedList<Runnable>();
// Fill others with implementors of Runnable...
for(Joinable joinable : joinables)
executor.execute(joinable);
for(Runnable runnable : others)
executor.execute(runnable);
for(Joinable joinable : joinables)
joinable.join();
// Continue, no matter what the threads in others are up to.
}
这是解决这个问题的好方法(它甚至安全吗?),还是有更好的方法?