CountDownLatch、CyclicBarrier、Semaphore

11 篇文章 1 订阅
1 篇文章 0 订阅

一、CountDownLatch

1.CountDownLatch原理:

CountDownLatch 是基于计数器的原理实现的, 它内部维护了一个整型的计数器。创建 CountDownLatch 对象时, 需要指定一个初始计数值, 该计数值表示需要等待的线程数量,使用其 await() 方法让其等待。每当一个线程完成了其任务, 可以调用 CountDownLatch 的 countDown() 方法, 计数器的值就会减一。当计数器的值变成 0 时, 等待的线程就会被唤醒, 继续执行它们的任务。

2.示例:
class CountDownLatchDemo{
    public static void mian() throw InterruptedException{
        //创建倒计时门闩对象
        CountDownLatch latch = new CountDownLatch(5);
        for(int i = 1 ; i <= 5 ; i++){
            new Thread(()->{
                try {
                    //模拟耗时操作
                    Thread.sleep(1000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println( i + "号线程执行完毕。");
                //计数器减一
                latch.countDown();
            } , i + "");
        }
        //主线程等待其他五个线程执行完后才继续执行
        downLatch.await();
        //await() 的重载方法,当计数器计数为0或者等待时间到达 5 秒,主线程会被唤醒
        //downLatch.await( 5 , TimeUnit.SECONDS );
        System.out.println( "其他线程全部执行完毕,主线程继续运行。");
    }
}

二、CyclicBarrier

1.CyclicBarrier原理:

CyclicBarrier 可以让一组线程互相等待,直到所有线程都到达某个公共屏障点(Barrier point)。它是一个循环栅栏,因为线程可以在屏障点再次达到后重新进行等待。CyclicBarrier 的使用需要指定两个参数:参与的线程数和屏障触发时的处理程序。当指定数量的线程到达屏障点时,所有线程都会被唤醒,并且可以执行一些共享的操作。在 CyclicBarrier 中,线程在等待时会释放所占用的资源,因此它适用于在多线程环境下同步多个线程完成任务的情况。它也常用于实现并行计算和并发测试的场景。同时,CyclicBarrier 是可以重复使用的,只需要调用其 reset() 方法,便可将屏障恢复至初始状态。

2.示例:
class CyclicBarrierDemo{
    public static void main(String[] args) {  
        // 创建一个CyclicBarrier,指定参与的线程数和屏障触发时的处理程序  
        CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {  
            @Override  
            public void run() {  
                System.out.println("所有线程都已到达屏障点,开始执行任务...");
                // 在这里执行需要所有线程共同完成的任务  
            }  
        });  
        // 创建3个线程,分别执行不同的任务  
        Thread thread1 = new Thread(()->{
            try {
                //模拟耗时操作
                Thread.sleep(1000);
                //线程到达屏障点,等待其他线程
                System.out.println( "1号线程到达屏障点。");
                barrier.await();
                //await() 的重载方法,当所有线程到达屏障点或者等待时间到达 5 秒,线程会被唤醒
                //barrier.await( 5 , TimeUnit.SECONDS);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }, "Thread-1");  
        Thread thread2 = new Thread(()->{
            try {
                Thread.sleep(1000);
                System.out.println( "2号线程到达屏障点。");
                barrier.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }, "Thread-2");  
        Thread thread3 = new Thread(()->{
            try {
                Thread.sleep(1000);
                System.out.println( "3号线程到达屏障点。");
                barrier.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }, "Thread-3");
        // 启动线程
        thread1.start();
        thread2.start();
        thread3.start();
        //将屏障回复至初始状态,之后便可以再次使用
        //barrier.reset()
    }
}

三、Semaphore

1.Semaphore原理:

Semaphore 用于控制或限制对资源的访问。它是一个计数信号量,可以用来保护一段代码或共享资源,确保同时只有一个线程可以访问它,就类似抢车位。Semaphore 的使用需要创建一个 Semaphore 对象,并使用它的 acquire() 和 release() 方法来控制资源的访问。当一个线程需要访问资源时,它会调用 acquire() 方法来获取一个许可。如果许可可用,线程将获取许可并继续执行。如果许可不可用,线程将被阻塞,直到有可用的许可。当线程完成对资源的访问后,它会调用 release() 方法来释放许可,以便其他线程可以获取许可并访问资源。

2.示例:
class SemaphoreDemo{
    public static void main(String[] args) {
    // 创建一个初始许可数为2的Semaphore,代表有两个车位
    Semaphore semaphore = new Semaphore(2);
    //创建4个线程,代表4辆汽车
    for(int i = 1; i <= 4;i++){
        Thread thread = new Thread(() -> {
            try {
                // 获取一个许可,代表抢到车位
                semaphore.acquire();
                System.out.println(i + "号汽车抢到车位");
                // 模拟对资源的访问,代表停车
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                // 释放许可,代表离开车位
                semaphore.release();
                System.out.println(i + "号汽车离开车位");
            }
        }).start();
    }
}
}

CountDownLatch 是一个计数器,它可以让一个或多个线程等待其他线程执行完毕后再继续执行。它的主要方法是 countDown() 和 await(),其中 countDown() 用于计数减一,await() 用于等待计数器变为0。与 CountDownLatch 相比,CyclicBarrier 的主要区别在于它可以重复使用,而且所有线程必须同时到达栅栏处才能继续执行后续任务。CyclicBarrier 的重要方法是 await(),并且可以通过构造方法传入一个 Runnable,在所有线程都到达栅栏状态时优先执行该动作。CyclicBarrier 内部使用 ReentrantLock 和 Condition 实现等待和唤醒的功能,通过维护一个 count 变量来记录还有多少个线程没有到达栅栏处。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [CountDownLatchCyclicBarrier](https://blog.csdn.net/weixin_44442186/article/details/123985119)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JUC多线程:CountDownLatchCyclicBarrierSemaphore同步器原理总结](https://blog.csdn.net/a745233700/article/details/120688546)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leighteen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值