のノンブロッキング コンテナ バージョンを実装できたと思いますawait(long timeout, TimeUnit unit)
。
public final class CountDownLatchContainer {
private final Set<CountDownLatch> countDowns;
public CountDownLatchContainer(List<CountDownLatch> countDowns) {
this.countDowns = new HashSet<CountDownLatch>(countDowns);
}
public void await() throws InterruptedException {
for (CountDownLatch count : countDowns)
count.await();
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException{
boolean success = true;
ExecutorService e = Executors.newFixedThreadPool(countDowns.size());
List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>(countDowns.size());
for (CountDownLatch count : countDowns)
futures.add(e.submit(new SingleLatchTimeOutAwaiter(count, timeout, unit)));
for (Future<Boolean> f : futures) {
try {
success &= f.get();
} catch (ExecutionException e1) {
throw new InterruptedException();
}
}
e.shutdown();
return success;
}
private static class SingleLatchTimeOutAwaiter implements Callable<Boolean> {
private final CountDownLatch count;
private final long timeout;
private final TimeUnit unit;
private SingleLatchTimeOutAwaiter(CountDownLatch count, long timeout,
TimeUnit unit) {
this.count = count;
this.timeout = timeout;
this.unit = unit;
}
public Boolean call() throws Exception {
return count.await(timeout, unit);
}
}
}
そして、ここにテストケースがあります。それはかなり正確です。
public class CountDownLatchContainerTest {
public static void main(String[] args) throws InterruptedException {
ExecutorService e = Executors.newFixedThreadPool(3);
CountDownLatch c1 = new CountDownLatch(1);
CountDownLatch c2 = new CountDownLatch(1);
CountDownLatchContainer c = new CountDownLatchContainer(Arrays.asList(
c1, c2));
e.submit(new MultiWaiter(c, 4, TimeUnit.SECONDS));
Thread.sleep(1000);
e.submit(new MultiWaiter(c, 2, TimeUnit.SECONDS));
e.submit(new MultiWaiter(c, 3, TimeUnit.SECONDS));
c1.countDown();
int hundredth = 29; // 1/100 s delay
for (int i = hundredth; i --> 0;) {
Thread.sleep(100);
}
c2.countDown();
e.shutdown();
}
private static class MultiWaiter implements Callable<Void> {
private static final AtomicInteger instanceCounter = new AtomicInteger(
0);
private final int instance;
private final CountDownLatchContainer c;
private final long timeout;
private final TimeUnit unit;
private MultiWaiter(CountDownLatchContainer c, long timeout,
TimeUnit unit) {
this.c = c;
this.timeout = timeout;
this.unit = unit;
this.instance = instanceCounter.getAndIncrement();
}
public Void call() throws Exception {
System.out.println(getClass().getSimpleName() + "#" + instance
+ " is waiting...");
System.out.println(getClass().getSimpleName() + "#" + instance
+ " is in time: " + c.await(timeout, unit));
System.out.println(getClass().getSimpleName() + "#" + instance
+ " is released!");
return null;
}
}
}
出力
MultiWaiter#0 は待っています...
MultiWaiter#1 は待っています...
MultiWaiter#2 は待っています...
MultiWaiter#1 は間に合います: false
MultiWaiter#1 が解放されました!
MultiWaiter#0 is in time: true
MultiWaiter#0 が解放されました!
MultiWaiter#2 is in time: true
MultiWaiter#2 がリリースされました!