阅读文本大概需要3分钟。
在Java中CycliBarriar和CountdownLatch有什么区别?CyclicBarrier可以重复使用,而CountdownLatch不能重复使用。
Java的concurrent包里面的CountDownLatch其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是同时只能有一个线程去减这个计数器里面的值。可以向CountDownLatch对象设置一个初始的数字作为计数值,任何调用这个对象上的await()方法都会阻塞,直到这个计数器的计数值被其他的线程减为0为止。所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。
CountDownLatch一个非常典型的应用场景:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。
CyclicBarrier一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的 barrier。
总结如下:
0x01:CountDownLatch类只提供了一个构造器:
public CountDownLatch(int count) {
//参数count为计数值
}
然后下面这3个方法是CountDownLatch类中最重要的方法:
public void await() throws InterruptedException {
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
}
public void countDown() {
//将count值减1
}
CountDownLatch, 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
例子代码:
import java.util.concurrent.CountDownLatch;
public class countDownlatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(5);
for(int i=0;i<5;i++){
new Thread(new readNum(i,countDownLatch)).start();
}
countDownLatch.await();
System.out.println("线程执行结束。。。。");
}
static class readNum implements Runnable{
private int id;
private CountDownLatch latch;
public readNum(int id,CountDownLatch latch){
this.id = id;
this.latch = latch;
}
@Override
public void run() {
synchronized (this){
System.out.println("id:"+id);
latch.countDown();
System.out.println("线程组任务"+id+"结束,其他任务继续");
}
}
}
}
输出结果:
id:1
线程组任务1结束,其他任务继续
id:0
线程组任务0结束,其他任务继续
id:2
线程组任务2结束,其他任务继续
id:3
线程组任务3结束,其他任务继续
id:4
线程组任务4结束,其他任务继续
线程执行结束。。。。
线程在countDown()之后,会继续执行自己的任务,而CyclicBarrier会在所有线程任务结束之后,才会进行后续任务。
0x02: CyclicBarrier用法
CyclicBarrier提供2个构造器
public CyclicBarrier(int parties, Runnable barrierAction) {
}
public CyclicBarrier(int parties) {
}
参数parties指让多少个线程或者任务等待至barrier状态;参数barrierAction为当这些线程都达到barrier状态时会执行的内容。
CyclicBarrier中最重要的方法就是await方法
public int await() throws InterruptedException, BrokenBarrierException {
//挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
}
public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException {
//让这些线程等待至一定的时间,如果还有线程没有到达barrier状态
//就直接让到达barrier的线程执行后续任务
举例说明
}
例子代码:
import java.util.concurrent.CyclicBarrier;
public class cyclicBarrierTest {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("线程组执行结束");
}
});
for (int i = 0; i < 5; i++) {
new Thread(new readNum(i,cyclicBarrier)).start();
}
//CyclicBarrier 可以重复利用,
// 这个是CountDownLatch做不到的
// for (int i = 11; i < 16; i++) {
// new Thread(new readNum(i,cyclicBarrier)).start();
// }
}
static class readNum implements Runnable{
private int id;
private CyclicBarrier cyc;
public readNum(int id,CyclicBarrier cyc){
this.id = id;
this.cyc = cyc;
}
@Override
public void run() {
synchronized (this){
System.out.println("id:"+id);
try {
cyc.await();
System.out.println("线程组任务" + id + "结束,其他任务继续");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
输出结果:
id:1
id:2
id:4
id:0
id:3
线程组执行结束
线程组任务3结束,其他任务继续
线程组任务1结束,其他任务继续
线程组任务4结束,其他任务继续
线程组任务0结束,其他任务继续
线程组任务2结束,其他任务继续
☆
往期精彩
☆
01 漫谈发版哪些事,好课程推荐
02 Linux的常用最危险的命令
03 互联网支付系统整体架构详解
04 优秀的Java程序员必须了解的GC哪些
05 IT大企业有哪些病,别被这些病毁了自己?
关注我每天进步一点点
你点的在看,我都当成了喜欢