В качестве альтернативы CountDownLatch вы также можете использовать CyclicBarrier например,
public class ThreadWaitEx {
static CyclicBarrier barrier = new CyclicBarrier(100, new Runnable(){
public void run(){
System.out.println("clean up job after all tasks are done.");
}
});
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new MyCallable(barrier));
t.start();
}
}
}
class MyCallable implements Runnable{
private CyclicBarrier b = null;
public MyCallable(CyclicBarrier b){
this.b = b;
}
@Override
public void run(){
try {
//do something
System.out.println(Thread.currentThread().getName()+" is waiting for barrier after completing his job.");
b.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
Для использования CyclicBarrier в этом случае барьер .await () должен быть последним оператором, т. Е. Когда ваш поток завершает свою работу. CyclicBarrier может быть снова использован с его методом reset (). Чтобы процитировать Javadocs:
CyclicBarrier поддерживает необязательную команду Runnable, которая запускается один раз для каждой точки барьера, после прибытия последнего потока в партии, но до того, как какие-либо потоки будут освобождены. Это барьерное действие полезно для обновления общего состояния до того, как какая-либо из сторон продолжит.