CountDownLatch和CyclicBarrier都属于juc并发包下的工具类;
从字面上理解,CountDown表示减法计数,Latch表示门闩的意思,计数为0的时候就可以打开门闩了。Cyclic Barrier表示循环的障碍物。两个类都含有这一个意思:对应的线程都完成工作之后再进行下一步动作,也就是大家都准备好之后再进行下一步。然而两者最大的区别是,进行下一步动作的动作实施者是不一样的。这里的“动作实施者”有两种,一种是主线程(即执行main函数),另一种是执行任务的其他线程,后面叫这种线程为“其他线程”,区分于主线程。对于CountDownLatch,当计数为0的时候,下一步的动作实施者是main函数;对于CyclicBarrier,下一步动作实施者是“其他线程”
CountDownLatch:使一个或多线程线程等待其他线程完成工作执行才能执行。
CyclicBarrier:允许一组线程互相等待,直到到达某个公共屏障点,才会进行后续任务。
CountDownLatch示例:
Thread[] threads = new Thread[5];
CountDownLatch countDownLatch = new CountDownLatch(threads.length);
for (int i = 0; i < threads.length; i++) {
int finalI = i;
threads[i] = new Thread(() -> {
System.out.println(finalI);
countDownLatch.countDown();
});
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" main ");
}
执行结果:
0
1
2
3
4
main
如代码所示:
1.首先初始化一个计数器
CountDownLatch countDownLatch = new CountDownLatch(threads.length);
2.启动5个线程,主线程阻塞
countDownLatch.await();
3.每次线程执行完都减1
countDownLatch.countDown();
4.当减为0时,主线程才最后执行
CyclicBarrier示例
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5,() -> System.out.println("满人,发车"));
for (int i = 0; i < 5; i++) {
int finalI = i;
new Thread(() -> {
try {
System.out.println(finalI);
cyclicBarrier.await();
System.out.println("await:"+ finalI);
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
执行结果:
0
3
2
1
4
满人,发车
await:4
await:2
await:0
await:3
await:1
总结:
CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。
CyclicBarrier : N个线程相互等待,任何一个线程没有到达或完成时,所有的线程都必须互相等待。
CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待
CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier