【JUC】六、辅助类

news/2024/5/20 10:19:56 标签: java, juc

文章目录

  • 1、CountDownLatch减少计数
  • 2、CyclicBarrier循环栅栏
  • 3、Semaphore信号灯

本篇整理JUC的几个同步辅助类:

  • 减少计数:CountDownLatch
  • 循环栅栏:CyclicBarrier
  • 信号灯:Semaphore

1、CountDownLatch减少计数

案例:6个同学陆续离开教室后,班长才可以锁门

先不使用CountDownLatch,看下效果:

java">public class CountDownDemo {

    public static void main(String[] args) {
       
        for (int i = 1; i < 7; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "号同学离开了教室");
            },String.valueOf(i)).start();
        }
        System.out.println(Thread.currentThread().getName() + " 班长锁门走人了");
    }
}

运行:这里循环执行6次start,创建6个就绪状态的线程后,main线程继续向下执行,而这6个新线程还要抢夺CPU时间片、执行,因此可能出现其他线程未执行结束,main线程(班长)就执行结束的情况。(先main线程中start创建线程,再抢时间片,抢到后才执行run方法,不要迷)

在这里插入图片描述

改进,引入CountDownLatch:

java">public class CountDownDemo {

    public static void main(String[] args) throws InterruptedException {
        //创建CountDownLatch对象,设置初始值
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i < 7; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "号同学离开了教室");
                //计数减一(因为到这儿,新线程的run方法也执行完了)
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }
        //计数器未成0前,让当前线程(main线程)挂起
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + " 班长锁门走人了");
    }
}

在这里插入图片描述

CountDownLatch类的常用方法

  • 构造器方法,传入初始的计数
java">CountDownLatch(int count)
  • 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断
java">void await()
  • 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间
java">boolean await(long timeout, TimeUnit unit)
  • 锁存器计数减一
java">void countDown()
  • 返回当前计数
java">long getCount()

总结

  • 定义计数器初始值
  • 每次相关操作后,让计数器减一
  • 计数器的值没变成0 ,当前线程就一直await,等计数器变成0后,await后面的代码才会继续执行

2、CyclicBarrier循环栅栏

作用

让一组线程互相等待,直到达到某个公共的屏障点。且可以在达到这个公共屏障点后(在一组线程中的最后一个线程到达之后,但在释放所有线程之前)执行一个Runnable。注意不是新开一个线程去执行,而是由最后一个进入 barrier 的线程执行。

案例:集齐7颗龙珠才可以召唤神龙

java">public class CyclicDemo {

    //设置固定值
    private static final int NUMBER = 7;

    public static void main(String[] args) {
        //创建CyclicBarrier
        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
            System.out.println("集齐7颗龙珠,召唤神龙成功!");
        });
        //集齐七颗龙珠的过程
        for (int i = 1; i <= 7 ; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "星龙珠被收集到了");
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }

    }
}

运行:

在这里插入图片描述

修改参数,让for循环跑6次(即只创建6个线程去调用await,刻意不让其到达number),而number仍然为7,此时运行,程序一直等待,最后exit -1

在这里插入图片描述
CyclicBarrier类的常用方法

  • 构造方法,传入参与线程的数量,和最后要执行的操作
java">CyclicBarrier(int parties, Runnable barrierAction)
  • 在所有参与线程未调用CyclicBarrier对象的await方法之前,将一直等待,也就是上面演示的达到不了那个number。这些参与的线程,在其最后调用await,就相当于在说我已在当前屏障出等待。而若有参与线程不调用await,就像春游发车前少个人一样,只能整个线程组都等着。
java">int await()
  • 同上,未到屏障点前,所有调用了await的线程(参与线程)就一直等待,除非到了超时时间
java">await(long timeout, TimeUnit unit)
  • 返回当前已到达屏障点的线程的数量(春游实际到上车点的人数)
java">int getNumberWaiting()
  • 返回传入的屏障点(春游报名人数)
java">int getParties()

总结

Barrier,屏障,参与的线程调一次await,即说明该线程已在屏障出等待,屏障点+1,达到这个屏障点,线程组的所有线程才继续往下执行,否则之前调用了await方法的线程就一直处于await等待状态,除非到了指定的超时时间

3、Semaphore信号灯

作用

维护一个信号量,这个信号量里有多个许可,拿到许可就执行,没拿到就等着。有点像对象锁了,而和对象锁不同的是,一个对象,一把对象锁,但Semaphore的这个锁(许可)的数量是你自己传入的。

案例:6辆汽车,停三个停车位

车停在车位A,其他车就不能再停在A位了,这就是获取一个许可。车开出去,就是释放一个许可

acquire获取许可证后,其他线程只能一直等待,阻塞状态

java">public class SemaphoreDemo {

    public static void main(String[] args) {
        //创建Semaphore,设置许可数量,三个车位,对应三个许可证
        Semaphore semaphore = new Semaphore(3);
        //模拟6辆汽车
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    //抢占许可证
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "抢到了车位");
                    //设置一个5s以内的随机时间,模拟停车
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                    System.out.println(Thread.currentThread().getName() + "=====> 离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //释放许可
                    semaphore.release();
                }
            },String.valueOf(i)).start();


        }
    }
}

运行:

在这里插入图片描述

Semaphore类的常用方法

  • 构造方法,传入一个数字,如果把Semaphore类看成我们前面并发编程步骤里的资源类,那这个数字就是设置有几把对象锁
java">Semaphore(int permits)
  • 构造方法重载,可传入一个Boolean,表示是否公平的给许可证,设置false时,是允许新启动的线程插队的,设置为true,则按照先进先出的方式来在等待的线程队列中选择线程,发放许可
java">Semaphore(int permits, boolean fair)
  • 获取许可
java">void acquire()
  • 释放许可
java">void release()

在这里插入图片描述

总结

个人理解就是,如果把Semaphore类看成我们前面并发编程步骤里的资源类,那它特殊的地方就是,这个资源类的一个对象有几把对象锁,是我们可以自己在构造方法里设置的,而普通的自定义资源类,想要n把对象锁,就得new上n个对象。


最后,API文档地址:https://tool.oschina.net/apidocs/apidoc?api=jdk-zh


http://www.niftyadmin.cn/n/5184619.html

相关文章

上海亚商投顾:沪指震荡反弹 汽车产业链多股涨停

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 指数早间高开后震荡回落&#xff0c;三大股指最终均小幅上涨。汽车产业链持续活跃&#xff0c;华为汽车方向领…

WPF小知识

在编写WPF程序遇到一些小问题&#xff0c;所以记录起来&#xff0c;查其他方便。 Label自动换行 网上搜的都不能自动换行&#xff0c;发现使用Run 就可以。在脚本中直接调用labTip.Text进行赋值就可以了。 <Label Foreground"#FF9E9E9E" FontSize"16"…

ROS2 与 Gazebo 联合仿真项目模版

系列文章目录 文章目录 系列文章目录前言一、包含的软件包二、安装2.1 安装要求2.2 作为模板使用 三、用法3.1 安装依赖项3.2 构建项目3.3 source 工作空间3.4 启动仿真 四、详细用法4.1 软件包结构4.2 仿真资源配置 总结 前言 一个集成了 ROS 2 和 Gazebo 模拟器的模板项目。…

基于模拟退火算法的TSP问题建模求解(Python)

基于模拟退火算法的TSP问题建模求解&#xff08;Python&#xff09; 一、模拟退火算法&#xff08;Simulated Annealing Algorithm&#xff0c;SAA&#xff09;工程背景模拟退火算法用于优化问题求解原理 二、旅行商问题&#xff08;Travelling salesman problem&#xff0c;TS…

微信小程序相机相册授权后,需要重启客户端才能正常调用相机,无法调起窗口选择图片,无反应解决方案

最近微信小程序很多功能突然不能使用&#xff0c;本篇针对无法调起相册进行说明 解决方案 检查小程序隐私协议是否配置&#xff0c;操作步骤这里不在详细说明&#xff0c;点击教程按照上面的教程&#xff0c;找到入口后点击完善或者更新 选择选中的照片或视频这个权限要申请 之…

AUTOSAR汽车电子嵌入式编程精讲300篇-面向车载CAN网络的路由和ECU刷写方法 (中)

目录 3.3 面向FOTA的CAN网络“高层协议”分层设计 3.3.1 ENCAP-CAN网络层设计 3.3.2 ENCAP-CAN传输层设计

StyleGAN:彻底改变生成对抗网络的艺术

一、介绍 多年来&#xff0c;人工智能领域取得了显着的进步&#xff0c;其中最令人兴奋的领域之一是生成模型的发展。这些模型旨在生成与人类创作没有区别的内容&#xff0c;例如图像和文本。其中&#xff0c;StyleGAN&#xff08;即风格生成对抗网络&#xff09;因其创建高度逼…

Qt 5.15.2 Windows 子目录项目: undefined reference to `vtable for xxx‘

网上查了很多资料&#xff0c;都在说是 Q_OBJECT 的问题&#xff0c;但是不适用我的项目。 首先我有一个子目录项目&#xff0c;专门承载基础的 UI 控件&#xff0c;其中有这么一个&#xff1a; #ifndef HOVERBUTTON_H #define HOVERBUTTON_H#include "QtCore/qcoreeven…