CyclicBarrier与CountDownLatch很像,都是可以同步多个线程,不同的是
1.CountDownLatch只能由外部线程等待线程池线程结束,而CyclicBarrier在构造是可以传入一个Runnable参数,用于当Count减为0时继续执行的线程
2.CountDownLatch.countDown()方法并不会阻塞,而是线程将计数减一后继续运行至结束,而CyclicBarrier调用await()方法会将计数减一,如果计数此时不等于0,则会在此阻塞,也就是说,当最后于1个线程将count减为0时,所有线程同时执行,同时执行传入的线程完成后续的汇总工作
3.CyclicBarrier如其名字,可以循环使用,每次计数减为0后,所有线程执行结束后,Count的值自动变为原来的值,而CountDownLatch不可复用,Count减为0后就不能继续使用了
基本用法:
public class test {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(2, () -> {//构造方法传入汇总线程
System.out.println("task1 task2 全部执行结束");
});
new Thread(()->{
System.out.println("task1 start");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
System.out.println("task1 finish");
},"task1").start();
new Thread(()->{
System.out.println("task2 start");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
System.out.println("task2 finish");
},"task2").start();
}
}
重复使用:
for (int i = 0; i < 3; i++) {//重复利用
new Thread(()->{
System.out.println("task1 start");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
System.out.println("task1 finish");
},"task1").start();
new Thread(()->{
System.out.println("task2 start");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
System.out.println("task2 finish");
},"task2").start();
注意:
如果使用线程池做循环执行的话,线程池的核心线程数如果大于任务数,可能导致第一遍的任务还没都执行完时,第二遍的任务先将count减为0,此时第一轮最后的几个线程还未结束,汇总信息可能出错