说说JUC三个类:CountDownLatch,CyclicBarrier和Semaphore

本文详细介绍了Java并发库中的CountDownLatch倒计时器,CyclicBarrier同步屏障和Semaphore信号量,它们在控制线程执行顺序和资源访问方面的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在JUC中,有三个工具类来辅助我们进行并发编程,分别是 CountDownLatch,CyclicBarrier和Semaphore

CountDownLatch

英文意味倒计时器。顾名思义,它能够让某个线程等待,直到倒计时结束再执行

假如我想让主线程最后执行。看如下代码(未加CountDownLatch):

public class CountDownLatchTest {

    public static void main(String[] args) {
        int t = 5;
        for (int i = 0;i<t;i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"正在执行");
            }).start();
        }
        System.out.println("主线程执行");
    }
}

---------------结果----------------
主线程执行
Thread-1正在执行
Thread-2正在执行
Thread-0正在执行
Thread-3正在执行
Thread-4正在执行

现在加上CountDownLatch

public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        int t = 5;
        CountDownLatch countDownLatch = new CountDownLatch(t);
        for (int i = 0;i<t;i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"正在执行");
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("主线程执行");
    }
}
------------结果------------
Thread-0正在执行
Thread-2正在执行
Thread-3正在执行
Thread-1正在执行
Thread-4正在执行
主线程执行

CyclicBarrier

字面意思回环栅栏。就是让一组线程等待至同一个状态后再继续全部执行

看如下代码,假设我想让全部线程先打印第一句话后再打印第二句话,最后在打印第三句话
未加CyclicBarrier

public class CyclicBarrierTest {
    public static void main(String[] args) {
        int t = 5;
        for (int i = 0;i<t;i++){
            new Thread(()->{
                 System.out.println(Thread.currentThread().getName()+"开始执行");
                 System.out.println(Thread.currentThread().getName()+"正在执行");
                 System.out.println(Thread.currentThread().getName()+"执行完毕");
            }).start();
        }
    }
}
------------结果-------------
Thread-0开始执行
Thread-2开始执行
Thread-1开始执行
Thread-1正在执行
Thread-2正在执行
Thread-2执行完毕
Thread-1执行完毕
Thread-0正在执行
Thread-3开始执行
Thread-3正在执行
Thread-3执行完毕
Thread-4开始执行
Thread-4正在执行
Thread-4执行完毕
Thread-0执行完毕

加上CyclicBarrier

public class CyclicBarrierTest {
    public static void main(String[] args) {
        int t = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(t);
        for (int i = 0;i<t;i++){
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+"开始执行");
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName()+"正在执行");
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName()+"执行完毕");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
------------结果-------------
Thread-0开始执行
Thread-2开始执行
Thread-1开始执行
Thread-3开始执行
Thread-4开始执行
Thread-4正在执行
Thread-2正在执行
Thread-3正在执行
Thread-0正在执行
Thread-1正在执行
Thread-1执行完毕
Thread-3执行完毕
Thread-2执行完毕
Thread-4执行完毕
Thread-0执行完毕

CyclicBarrier还提供Runnable参数,可以在所有线程执行完毕后进行额外操作
代码如下:

public class CyclicBarrierTest {
    public static void main(String[] args) {
        int t = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(t, new Runnable() {
            @Override
            public void run() {
                System.out.println("======================");
            }
        });
        for (int i = 0;i<t;i++){
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+"开始执行");
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName()+"正在执行");
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName()+"执行完毕");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
-----------结果--------------
Thread-0开始执行
Thread-1开始执行
Thread-3开始执行
Thread-4开始执行
Thread-2开始执行
======================
Thread-2正在执行
Thread-0正在执行
Thread-3正在执行
Thread-1正在执行
Thread-4正在执行
======================
Thread-4执行完毕
Thread-2执行完毕
Thread-1执行完毕
Thread-3执行完毕
Thread-0执行完毕

Semaphore

意为信号量。有点像锁,是对锁的扩展。信号量可以指定多个线程同时访问一个资源,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
假设银行有5个窗口,10个顾客,只有当窗口被释放了,下一个顾客才能去办业务;
用Semaphore的话很容易就实现

public class SemaphoreTest {
    public static void main(String[] args) {
        int t = 10;
        Semaphore semaphore = new Semaphore(5);
        for (int i = 0;i<t;i++){
            int finalI = i;
            new Thread(()->{
                try {
                    semaphore.acquire();
                    System.out.println("顾客"+ finalI +"正在办理业务,占用窗口");
                    Thread.sleep(2000);
                    System.out.println("顾客"+ finalI +"业务办理成功,释放窗口");
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
-----------结果--------------
顾客0正在办理业务,占用窗口
顾客1正在办理业务,占用窗口
顾客2正在办理业务,占用窗口
顾客3正在办理业务,占用窗口
顾客4正在办理业务,占用窗口
顾客0业务办理成功,释放窗口
顾客5正在办理业务,占用窗口
顾客2业务办理成功,释放窗口
顾客1业务办理成功,释放窗口
顾客6正在办理业务,占用窗口
顾客7正在办理业务,占用窗口
顾客3业务办理成功,释放窗口
顾客8正在办理业务,占用窗口
顾客4业务办理成功,释放窗口
顾客9正在办理业务,占用窗口
顾客5业务办理成功,释放窗口
顾客8业务办理成功,释放窗口
顾客7业务办理成功,释放窗口
顾客9业务办理成功,释放窗口
顾客6业务办理成功,释放窗口

总结

CountDownLatch和CyclicBarrier 都能实现线程之间的等待。
CountDownLatch是让某线程在其他所有线程都执行后才执行。
CyclicBarrier是让一组相互等待到某一个阶段后再继续一起往下执行。
Semaphore有点像锁,一般用于控制对某组资源的访问权限。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值