Java 并发编程 (二)CountDownLatch和CyclicBarrier的使用

文章介绍了Java并发工具类CountDownLatch和CyclicBarrier的用法和场景。CountDownLatch用于一个线程或多个线程等待其他线程完成操作,常用于并发测试中的等待所有线程完成。CyclicBarrier则提供阶段性同步,允许一组线程彼此等待,重置后可重复使用,适合多阶段计算任务。文章通过实例展示了它们在比赛场景中的应用。
摘要由CSDN通过智能技术生成

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);

    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值