CountDownLatch和CyclicBarrier
CountDownLatch
功能介绍
CountDownLatch 是一个同步功能的辅助类 线程计数不为0时呈wait状态如果为0则继续执行。通过await 和 countDown 两个方法来实现等待和继续运行。
作用:一个线程或多个线程等待另一个线程或多个线程完成后再继续执行。
public class MyCountDownLatch {
    private CountDownLatch countDownLatch = new CountDownLatch(1);
    public void test(){
        try {
            System.out.println("start await");
            //等待
            countDownLatch.await();
            System.out.println("end await");
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    public void downTest(){
        System.out.println("start countDown");
        countDownLatch.countDown();
    }
    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThread extends Thread{
        private MyCountDownLatch countDownLatch = new MyCountDownLatch();
        @Override
        public void run(){
            countDownLatch.test();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyCountDownLatch myCountDownLatch = new MyCountDownLatch();
        MyThread myThread = new MyThread(myCountDownLatch);
        myThread.start();
        Thread.sleep(1000);
        myCountDownLatch.downTest();
    }
}

await() 存在线程阻塞的风险 可以使用 await(long timeout, TimeUnit unit) 在最大时间内进入waiting状态,超过后会自动唤醒,防止阻塞
getCount() 可以获取当前计数的值
应用场景
- 裁判员等待全部运动员回来
public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        System.out.println("start wait");
        for (int i = 0; i < 5; i++){
            MyThreadA myThreadA = new MyThreadA(countDownLatch);
            myThreadA.setName("runner" + i);
            myThreadA.start();
        }
        countDownLatch.await();
        System.out.println("all back");
    }
    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThreadA extends Thread{
        private CountDownLatch countDownLatch;
        @Override
        public void run(){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " countDown");
            countDownLatch.countDown();
        }
    }

- 准备比赛
public class MyCountDownLatch {
    private CountDownLatch countDownLatch = new CountDownLatch(1);
    public void awaitStart(){
        try {
            System.out.println(Thread.currentThread().getName() + " start await");
            countDownLatch.await();
            System.out.println(Thread.currentThread().getName() + " end await");
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    public void downCount(){
        System.out.println(Thread.currentThread().getName() + " start countDown");
        countDownLatch.countDown();
    }
    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThread extends Thread{
        private MyCountDownLatch countDownLatch = new MyCountDownLatch();
        @Override
        public void run(){
            countDownLatch.awaitStart();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyCountDownLatch countDownLatch = new MyCountDownLatch();
        System.out.println("start wait");
        for (int i = 0; i < 3; i++){
            MyThread myThread = new MyThread(countDownLatch);
            myThread.setName("runner" + i);
            myThread.start();
        }
        Thread.sleep(2000);
        countDownLatch.downCount();
        System.out.println("all back");
    }
}

CyclicBarrier
功能介绍
CyclicBarrier 具有CountDownLatch的所有功能还可以实现屏障(阶段性同步)等能力。
作用:多个线程之间相互等待,任何一个线程完成之前所有线程都必须等待。
与CountDownLanch相同的功能不再介绍
public class MyCyclicBarrier {
    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThread extends Thread{
        private CyclicBarrier cyclicBarrier;
        @Override
        public void run() {
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        MyThread myThread = new MyThread(cyclicBarrier);
        myThread.start();
        Thread.sleep(1000);
        System.out.println(cyclicBarrier.getNumberWaiting());
        MyThread myThread1 = new MyThread(cyclicBarrier);
        myThread1.start();
        Thread.sleep(1000);
        System.out.println(cyclicBarrier.getNumberWaiting());
        MyThread myThread2 = new MyThread(cyclicBarrier);
        myThread2.start();
        Thread.sleep(1000);
        System.out.println(cyclicBarrier.getNumberWaiting());
        MyThread myThread3 = new MyThread(cyclicBarrier);
        myThread3.start();
        Thread.sleep(1000);
        System.out.println(cyclicBarrier.getNumberWaiting());
    }
}

可以看出CyclicBarrier具有屏障的重制性计数值可以重制为0
isBroken() 查询屏障是否属于破损状态
getNumberWaiting() 查看有几个线程到达屏障点
getParties() 获取 parties 个数
reset() 重制屏障
应用场景
- 阶段跑步比赛
public class MyCyclicBarrier {
    public CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
    private void start(){
        try {
            int sleepValue = (int) (Math.random() * 10000);
            Thread.sleep(sleepValue);
            System.out.println(Thread.currentThread().getName() + " start 第一阶段");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName() + " end 第一阶段");
            int sleepValue1 = (int) (Math.random() * 10000);
            Thread.sleep(sleepValue1);
            System.out.println(Thread.currentThread().getName() + " start 第二阶段");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName() + " end 第二阶段");
        }catch (InterruptedException | BrokenBarrierException e){
            e.printStackTrace();
        }
    }
    @AllArgsConstructor
    @NoArgsConstructor
    public static class MyThread extends Thread{
        private MyCyclicBarrier cyclicBarrier;
        @Override
        public void run() {
            cyclicBarrier.start();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyCyclicBarrier cyclicBarrier = new MyCyclicBarrier();
        MyThread myThread = new MyThread(cyclicBarrier);
        myThread.setName("myThread");
        myThread.start();
        Thread.sleep(1000);
        MyThread myThread1 = new MyThread(cyclicBarrier);
        myThread.setName("myThread1");
        myThread1.start();
        Thread.sleep(1000);
        MyThread myThread2 = new MyThread(cyclicBarrier);
        myThread.setName("myThread2");
        myThread2.start();
        Thread.sleep(1000);
        MyThread myThread3 = new MyThread(cyclicBarrier);
        myThread.setName("myThread3");
        myThread3.start();
        Thread.sleep(1000);
    }
}




















