CyclicBarrier和CountDownLatch区别

CyclicBarrier和CountDownLatch区别

参考CyclicBarrier和CountDownLatch区别

读完上边

的分析后,按照自己的理解,写个demo

场景:

有一辆列车A8888 从始发地开往北京
途中,收到了列车调度室的让道指令
需要暂时让道2辆动车驶过先
待收到重新启动命令后,再行启动重新出发

  • CountDownLatch

代码:

import java.util.concurrent.CountDownLatch;

/**
 * usage:multy thread ,count down latch(tanhuang lock)
 *
 * @author W
 * @version Id: CountDownLatchTest.java , 2018/07/27 14:28  W Exp $$
 */
public class CountDownLatchTest {

    private static final int YouFirstThreadCount = 2;//需要让道的动车辆数
    static CountDownLatch countDownLatch = new CountDownLatch(YouFirstThreadCount);

    //Latch read [lætʃ]

    public static void main(String args[]) throws InterruptedException {
        System.out.println("普列A8888号启动开往北京.....\n");

        System.out.println("\n调度室指令:\n\t\t请普列A8888号让道其他列车行驶...");

        System.out.println("\n普列A8888号准备让道其他动车....\n");
        toLetOtherFirst();

        System.out.println("\n普列A8888号准备重新启动开往北京....");
    }

    private static void toLetOtherFirst() throws InterruptedException {
        for (int i=0;inew Thread(new ReadNum(i,countDownLatch)).start();
        }
        countDownLatch.await();
    }

    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+1)+"号已开过让车地....");
                latch.countDown();
                if ( latch.getCount() == 0) {
                    System.out.println("\n调度室指令:\n\t\t受让车数量为0,已完成让道任务,请继续启动行车...");
                }
            }
        }
    }
}

输出结果:

普列A8888号启动开往北京.....


调度室指令:
        请普列A8888号让道其他列车行驶...

普列A8888号准备让道其他动车....

动车1号已开过让车地....
动车2号已开过让车地....

调度室指令:
        受让车数量为0,已完成让道任务,请继续启动行车...

普列A8888号准备重新启动开往北京....

Process finished with exit code 0

从上边可以看出,列车A8888(可以理解成主线程),其他动车(其他线程)
共同形成多线程环境

待动车组(2辆)先行开过,这个为先行事件 threads.start()

先行事件启动后,列车A8888开始进入等待阻塞状态 latch.await()

thread内部run完后,latch.countDown();//超过一辆,计算一辆

当 latch.getCount() == 0 ,列车会从await态到唤醒状态

整个过程就是这样子

CountDownLatch 0时释放所有等待的线程,计数为0时,无法重置,不可重复利用

  • CyclicBarrier

代码:



import java.util.concurrent.CyclicBarrier;

/**
 * 循环
 *
 * @author W
 * @version Id: CyclicBarrierTest.java , 2018/07/27 15:07  W Exp $$
 */
public class CyclicBarrierTest {

    private static final int YouFirstThreadCount = 4;//需要让道的动车辆数
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(YouFirstThreadCount,new Runnable() {
        @Override
        public void run() {
            System.out.println("\n调度室指令:\n\t\t受让车数量"+cyclicBarrier.getParties()+"辆,已完成让道任务,请继续启动行车...");
            System.out.println("\n普列A8888号准备重新启动开往北京....\n");
        }
    });

    public static void main(String[] args) throws InterruptedException {
        System.out.println("普列A8888号启动开往北京.....\n");

        System.out.println("\n调度室指令:\n\t\t请普列A8888号让道其他列车行驶...");

        System.out.println("\n普列A8888号准备让道其他动车....\n");


        for (int i = 0; i < cyclicBarrier.getParties(); i++) {
            new Thread(new readNum(i,cyclicBarrier)).start();
        }

        //CyclicBarrier 可以重复利用,
        //这个是CountDownLatch做不到的
        /*for (int i = 10; i < 10+cyclicBarrier.getParties(); 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){
                try {
                    System.out.println("动车"+(id+1)+"号已开过让车地....");
                    cyc.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

输出结果:

普列A8888号启动开往北京.....


调度室指令:
        请普列A8888号让道其他列车行驶...

普列A8888号准备让道其他动车....

动车1号已开过让车地....
动车2号已开过让车地....
动车4号已开过让车地....
动车3号已开过让车地....

调度室指令:
        受让车数量4辆,已完成让道任务,请继续启动行车...

普列A8888号准备重新启动开往北京....


Process finished with exit code 0

从输出结果看,CyclicBarrier照样可以实现CountDownLatch功能

使用上的区别:

  • 1

    • CountDownLatch 做减法计算,count=0,唤醒阻塞线程
    • CyclicBarrier 做加法计算,count=屏障值(parties),唤醒阻塞线程
  • 2

    • CyclicBarrier 比 CountDownLatch 更灵活,计数达到指定值时,计数置为0重新开始,可重复利用,还有个reset方法可使用

我们知道主线程执行,比Thread.start();里头的run()方法在时间上更快一些
为了确保某些定时任务或者特定的任务方法先执行完,再执行主线程,就可以这么干了.




你可能感兴趣的:(JAVA)