CycliBarriar和CountdownLatch有什么区别

阅读文本大概需要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类只提供了一个构造器:


     
     
  1. public CountDownLatch( int count) {  
  2.            //参数count为计数值

然后下面这3个方法是CountDownLatch类中最重要的方法:


     
     
  1. public void await() throws InterruptedException { 
  2.            //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
  3. }   
  4. public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
  5.            //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
  6. }
  7. public void countDown() {
  8.            //将count值减1
  9. }

CountDownLatch, 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

例子代码:


     
     
  1. import java.util.concurrent.CountDownLatch;
  2. public class countDownlatchTest {
  3.     public static void main(String[] args) throws InterruptedException {
  4.         CountDownLatch countDownLatch =  new CountDownLatch( 5);
  5.          for( int i= 0;i< 5;i++){
  6.              new Thread( new readNum(i,countDownLatch)).start();
  7.         }
  8.         countDownLatch.await();
  9.         System.out. println( "线程执行结束。。。。");
  10.     }
  11.     static class readNum  implements Runnable{
  12.         private  int id;
  13.         private CountDownLatch latch;
  14.         public readNum( int id,CountDownLatch latch){
  15.             this.id = id;
  16.             this.latch = latch;
  17.         }
  18.         @Override
  19.         public void run() {
  20.             synchronized (this){
  21.                 System.out. println( "id:"+id);
  22.                 latch.countDown();
  23.                 System.out. println( "线程组任务"+id+ "结束,其他任务继续");
  24.             }
  25.         }
  26.     }
  27. }

输出结果:


     
     
  1. id: 1
  2. 线程组任务 1结束,其他任务继续
  3. id: 0
  4. 线程组任务 0结束,其他任务继续
  5. id: 2
  6. 线程组任务 2结束,其他任务继续
  7. id: 3
  8. 线程组任务 3结束,其他任务继续
  9. id: 4
  10. 线程组任务 4结束,其他任务继续
  11. 线程执行结束。。。。

线程在countDown()之后,会继续执行自己的任务,而CyclicBarrier会在所有线程任务结束之后,才会进行后续任务。

0x02: CyclicBarrier用法

CyclicBarrier提供2个构造器


     
     
  1. public CyclicBarrier( int parties, Runnable barrierAction) {
  2. }
  3. public CyclicBarrier( int parties) {
  4. }

参数parties指让多少个线程或者任务等待至barrier状态;参数barrierAction为当这些线程都达到barrier状态时会执行的内容。

CyclicBarrier中最重要的方法就是await方法


     
     
  1. public  int await() throws InterruptedException, BrokenBarrierException { 
  2. //挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
  3. }
  4. public  int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { 
  5. //让这些线程等待至一定的时间,如果还有线程没有到达barrier状态
  6. //就直接让到达barrier的线程执行后续任务
  7. 举例说明
  8. }

例子代码:


     
     
  1. import java.util.concurrent.CyclicBarrier;
  2. public class cyclicBarrierTest {
  3.     public static void main(String[] args) throws InterruptedException {
  4.         CyclicBarrier cyclicBarrier =  new CyclicBarrier( 5new Runnable() {
  5.             @Override
  6.             public void run() {
  7.                 System.out. println( "线程组执行结束");
  8.             }
  9.         });
  10.          for ( int i =  0; i <  5; i++) {
  11.              new Thread( new readNum(i,cyclicBarrier)).start();
  12.         }
  13.          //CyclicBarrier 可以重复利用,
  14.          // 这个是CountDownLatch做不到的
  15. //        for (int i = 11; i < 16; i++) {
  16. //            new Thread(new readNum(i,cyclicBarrier)).start();
  17. //        }
  18.     }
  19.     static class readNum  implements Runnable{
  20.         private  int id;
  21.         private CyclicBarrier cyc;
  22.         public readNum( int id,CyclicBarrier cyc){
  23.             this.id = id;
  24.             this.cyc = cyc;
  25.         }
  26.         @Override
  27.         public void run() {
  28.             synchronized (this){
  29.                 System.out. println( "id:"+id);
  30.                 try {
  31.                     cyc.await();
  32.                     System.out. println( "线程组任务" + id +  "结束,其他任务继续");
  33.                 } catch (Exception e) {
  34.                     e.printStackTrace();
  35.                 }
  36.             }
  37.         }
  38.     }
  39. }

输出结果:


     
     
  1. id: 1
  2. id: 2
  3. id: 4
  4. id: 0
  5. id: 3
  6. 线程组执行结束
  7. 线程组任务 3结束,其他任务继续
  8. 线程组任务 1结束,其他任务继续
  9. 线程组任务 4结束,其他任务继续
  10. 线程组任务 0结束,其他任务继续
  11. 线程组任务 2结束,其他任务继续
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值