JUC高并发编程7:辅助类

news2024/11/24 14:11:05

1 减少计数CountDownLatch

1.1 CountDownLatch 概述

CountDownLatch 是 Java 并发包(java.util.concurrent)中的一个同步工具类,用于在多个线程之间进行协调。它允许一个或多个线程等待其他线程完成一组操作。

1.1.1 主要方法

  • CountDownLatch(int count):构造方法,初始化一个计数器,计数器的初始值为 count
  • void countDown():将计数器的值减 1。
  • void await():使当前线程等待,直到计数器的值变为 0。
  • boolean await(long timeout, TimeUnit unit):使当前线程等待,直到计数器的值变为 0,或者等待超时。

1.1.2 工作原理

  1. 初始化计数器:通过构造方法 CountDownLatch(int count) 初始化一个计数器,计数器的初始值为 count
  2. 线程等待:一个或多个线程调用 await() 方法,这些线程会阻塞,直到计数器的值变为 0。
  3. 计数器减 1:其他线程调用 countDown() 方法,将计数器的值减 1。调用 countDown() 方法的线程不会阻塞。
  4. 唤醒等待线程:当计数器的值变为 0 时,因 await() 方法阻塞的线程会被唤醒,继续执行。

1.2 示例代码

场景: 6 个同学陆续离开教室后值班同学才可以关门

public class CountDownLatchDemo {
    // 6个同学陆续离开教室之后,班长锁门
    public static void main(String[] args) throws InterruptedException {
        // 创建CountDownLatch对象,设置初始值
        int count = 6;
        CountDownLatch countDownLatch = new CountDownLatch(count);

        // 6个同学陆续离开教室之后
        for (int i = 1; i <= count; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + " 号同学离开了教室");

                // 计数器 -1
                countDownLatch.countDown();

            },String.valueOf(i)).start();
        }

        // 
        countDownLatch.await();

        System.out.println(Thread.currentThread().getName() + "班长锁门了");
    }
}

1.2.1 代码解释

  1. 初始化计数器
 int count = 6;
 CountDownLatch latch = new CountDownLatch(count);
  1. 创建并启动三个线程
for (int i = 1; i <= count; i++) {
	new Thread(()->{
    System.out.println(Thread.currentThread().getName() + " 号同学离开了教室");

    // 计数器 -1
    countDownLatch.countDown();

	},String.valueOf(i)).start();
}

  1. 主线程等待
// 主线程等待,直到计数器变为 0
 countDownLatch.await();

 System.out.println(Thread.currentThread().getName() + "班长锁门了");

1.3 小结

CountDownLatch 是一个非常有用的同步工具类,用于协调多个线程之间的执行顺序。通过初始化一个计数器,并使用 countDown()await() 方法,可以实现线程之间的等待和唤醒机制。在实际应用中,CountDownLatch 常用于等待一组线程完成某个任务后再继续执行后续操作。

2 循环栅栏CyclicBarrier

2.1 CyclicBarrier 概述

CyclicBarrier 是 Java 并发包(java.util.concurrent)中的一个同步工具类,用于协调多个线程之间的执行顺序。它允许一组线程互相等待,直到所有线程都到达一个共同的屏障点(barrier point),然后继续执行。

2.1.1 主要方法

  • CyclicBarrier(int parties):构造方法,初始化一个 CyclicBarrier,指定需要等待的线程数量。
  • CyclicBarrier(int parties, Runnable barrierAction):构造方法,初始化一个 CyclicBarrier,指定需要等待的线程数量,并在所有线程到达屏障点时执行一个指定的 Runnable 任务。
  • int await():使当前线程等待,直到所有线程都调用了 await() 方法,或者某个线程被中断。
  • int await(long timeout, TimeUnit unit):使当前线程等待,直到所有线程都调用了 await() 方法,或者某个线程被中断,或者等待超时。
  • int getParties():返回需要等待的线程数量。
  • boolean isBroken():查询此屏障是否处于损坏状态。
  • void reset():将屏障重置为其初始状态。

2.1.2 工作原理

  1. 初始化屏障:通过构造方法 CyclicBarrier(int parties)CyclicBarrier(int parties, Runnable barrierAction) 初始化一个 CyclicBarrier,指定需要等待的线程数量。
  2. 线程等待:每个线程调用 await() 方法,等待其他线程到达屏障点。
  3. 屏障点触发:当所有线程都调用了 await() 方法,屏障点被触发,所有线程继续执行。
  4. 可选的屏障动作:如果构造方法中指定了 Runnable 任务,则在所有线程到达屏障点后,执行该任务。
  5. 重用屏障CyclicBarrier 可以重复使用,当所有线程到达屏障点后,屏障会自动重置,等待下一组线程到达。

2.2 示例代码

场景: 集齐 7 颗龙珠就可以召唤神龙

public class CyclicBarrierDemo {

    // 创建固定值
    private static final int NUMBER = 7;

    public static void main(String[] args) {
        // 创建
        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
            System.out.println("集齐七颗龙珠就可以召唤神龙");
        });

        // 集齐七颗龙珠过程
        for (int i = 1; i <= 7; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + " 星龙珠被收集了");

                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }

            },String.valueOf(i)).start();
        }
    }
}

2.2.1 代码解释

  1. 初始化屏障
  private static final int NUMBER = 7;

  CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
          System.out.println("集齐七颗龙珠就可以召唤神龙");
  });
  1. 创建并启动七个线程
for (int i = 1; i <= 7; i++) {
           new Thread(()->{
               System.out.println(Thread.currentThread().getName() + " 星龙珠被收集了");

               try {
               		// 等待其他线程
                   cyclicBarrier.await();
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               } catch (BrokenBarrierException e) {
                   throw new RuntimeException(e);
               }

           },String.valueOf(i)).start();
       }

2.3 小结

CyclicBarrier 是一个非常有用的同步工具类,用于协调多个线程之间的执行顺序。通过初始化一个屏障,并使用 await() 方法,可以实现线程之间的等待和唤醒机制。CyclicBarrier 可以重复使用,适用于需要多个线程协同工作的场景。

3 信号灯Semaphore

3.1 Semaphore 概述

Semaphore 是 Java 并发包(java.util.concurrent)中的一个同步工具类,用于控制同时访问某个资源的线程数量。它通过许可证(permit)的概念来实现,每个许可证代表一个线程可以访问资源的权限。

3.1.1 主要方法

  • Semaphore(int permits):构造方法,初始化一个 Semaphore,指定最大信号量(许可证数量)。
  • Semaphore(int permits, boolean fair):构造方法,初始化一个 Semaphore,指定最大信号量(许可证数量),并设置是否使用公平锁(fairness)。
  • void acquire():获取一个许可证,如果没有可用的许可证,则阻塞当前线程,直到有许可证可用。
  • void acquire(int permits):获取指定数量的许可证,如果没有足够的许可证,则阻塞当前线程,直到有足够的许可证可用。
  • void release():释放一个许可证,将其返回给信号量。
  • void release(int permits):释放指定数量的许可证,将其返回给信号量。
  • int availablePermits():返回当前可用的许可证数量。
  • boolean tryAcquire():尝试获取一个许可证,如果成功则返回 true,否则返回 false
  • boolean tryAcquire(int permits):尝试获取指定数量的许可证,如果成功则返回 true,否则返回 false
  • boolean tryAcquire(long timeout, TimeUnit unit):尝试在指定时间内获取一个许可证,如果成功则返回 true,否则返回 false
  • boolean tryAcquire(int permits, long timeout, TimeUnit unit):尝试在指定时间内获取指定数量的许可证,如果成功则返回 true,否则返回 false

3.1.2 工作原理

  1. 初始化信号量:通过构造方法 Semaphore(int permits)Semaphore(int permits, boolean fair) 初始化一个 Semaphore,指定最大信号量(许可证数量)。
  2. 获取许可证:线程调用 acquire() 方法获取一个许可证,如果没有可用的许可证,则阻塞当前线程,直到有许可证可用。
  3. 释放许可证:线程调用 release() 方法释放一个许可证,将其返回给信号量。
  4. 控制并发访问:通过控制许可证的数量,可以限制同时访问某个资源的线程数量。

3.2 示例代码

场景: 抢车位, 6 部汽车 3 个停车位

public class SemaphoreDemo {
    public static void main(String[] args) {
        // 创建Semaphore,设置许可数量
         int permits = 3;
        Semaphore semaphore = new Semaphore(permits);

        // 模拟6辆汽车
        for (int i = 1; i <= 6; i++) {
            new Thread(()->{

                try {
                    //抢占
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"抢到了车位");
                    //设置随机停车时间
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));

                    System.out.println(Thread.currentThread().getName() + " ----离开了车位");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    // 释放
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }
    }
}
代码解释
  1. 初始化信号量
 int permits = 3;
 Semaphore semaphore = new Semaphore(permits);
  1. 创建并启动五个线程
for (int i = 1; i <= 6; i++) {
     new Thread(()->{

         try {
             //抢占
             semaphore.acquire();
             System.out.println(Thread.currentThread().getName()+"抢到了车位");
             //设置随机停车时间
             TimeUnit.SECONDS.sleep(new Random().nextInt(5));

             System.out.println(Thread.currentThread().getName() + " ----离开了车位");
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         } finally {
             // 释放
             semaphore.release();
         }
     },String.valueOf(i)).start();
 }

3.3 小结

Semaphore 是一个非常有用的同步工具类,用于控制同时访问某个资源的线程数量。通过初始化一个信号量,并使用 acquire()release() 方法,可以实现对并发访问的控制。Semaphore 适用于需要限制并发访问数量的场景,如资源池、连接池等。

4 思维导图

在这里插入图片描述

5 参考链接

【【尚硅谷】大厂必备技术之JUC并发编程】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2197670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【重学 MySQL】六十二、非空约束的使用

【重学 MySQL】六十二、非空约束的使用 定义目的关键字特点作用创建非空约束删除非空约束注意事项 在MySQL中&#xff0c;非空约束&#xff08;NOT NULL Constraint&#xff09;是一种用于确保表中某列不允许为空值的数据库约束。 定义 非空约束&#xff08;NOT NULL Constra…

基于LORA的一主多从监测系统_AHT20温湿度传感器

1&#xff09;AHT20温湿度传感器 这个传感器&#xff0c;网上能找到的资料还是比较多的&#xff0c;我们使用的是HAL硬件i2c&#xff0c;相比于模拟i2c&#xff0c;我们不需要过于关注时序问题&#xff0c;我们只需要关心如何获取数据以及数据如何处理&#xff0c;下面以数据手…

指针——指针数组、数组指针

&#xff08;一&#xff09;指针数组 1、本质&#xff1a;指针数组的本质任然是数组 2、基本格式&#xff1a;int* arr[5] 3、应用&#xff1a;如尝试使用指针来模拟二维数组 先来看代码 #include<stdio.h> //指针数组——模拟实现二维数组 int main() {int a[5] {…

java面向对象之类与对象

目录 1.定义一个类 案例:定义一个学生类 1.代码 2.效果 2.类的实例化与使用 1.代码 2.效果 3.访问控制 1)private 2)default 3)protected 4)public 注:如下图 4.封装一个类 案例:封装一个教师类 1)代码 2)效果 5.定义一个构造方法 1)无参数构造 2)有参数构造 3&#xff09;注 6…

【Java 问题】基础——反射

接上文 反射 49.什么是反射&#xff1f;应用&#xff1f;原理&#xff1f; 49.什么是反射&#xff1f;应用&#xff1f;原理&#xff1f; 什么是反射&#xff1f; 我们通常都是利用 new 方式来创建对象实例&#xff0c;这可以说就是一种“正射”&#xff0c;这种方式在编译时候…

HJDQN环境配置

git clone仓库代码等不做赘述 #创建&#xff0c;激活conda环境即可 conda create -n EAHJDQN python3.6 conda activate EAHJDQN#安装包 pip install mujoco_py2.0.2.8pip install Cython0.29.21pip install torch1.8.1cu111 torchvision0.9.1cu111 torchaudio0.8.1 -f https:/…

【信息论基础第四讲】信息的流动——平均互信息及其性质

一、平均互信息与互信息 1、互信息 互信息量表示接收到消息yj后&#xff0c;获得关于事件xi的信息量。 2、 从熵的角度来定义平均互信息量&#xff1a; 从信源X熵H(X)到信宿熵H(X|Y)熵减少了&#xff0c;同时为信宿Y提供了信息量&#xff0c;而信息从信源到信宿的变化是流经信…

每日OJ题_牛客_平方数_数学_C++_Java

目录 牛客_平方数_数学 题目解析 C代码1暴力 C代码2数学 Java代码数学 牛客_平方数_数学 平方数 (nowcoder.com) 描述&#xff1a; 牛妹是一个喜欢完全平方数的女孩子。 牛妹每次看到一个数 x&#xff0c;都想求出离 x 最近的完全平方数 y。 每次手算太麻烦&#xff0c;…

分享几个国外SSL证书提供商网站

国外SSL证书提供商 众所周知兼容性高的SSL证书肯定是在国外申请的&#xff0c;主要确保SSL证书的安全性的同时&#xff0c;对于安全标准在国外相比而言更成熟&#xff0c;保护程度也比较高。 另方面对需要申请的域名没有限制&#xff0c;可选性SSL证书类型种类比较多&#xf…

[Python学习日记-39] 闭包是个什么东西?

[Python学习日记-39] 闭包是个什么东西&#xff1f; 简介 闭包现象 闭包意义与作用 简介 在前面讲函数和作用域的时候应该提到过&#xff0c;当函数运行结束后会由 Python 解释器自带的垃圾回收机制回收函数内作用域已经废弃掉的变量&#xff0c;但是在 Python 当中还有一种…

vulnhub靶场之hackableIII

一.环境搭建 1.靶场描述 Focus on general concepts about CTF Difficulty: Medium This works better with VirtualBox rather than VMware. 2.靶场下载 https://download.vulnhub.com/hackable/hackable3.ova 3.靶场启动 二.信息收集 1.寻找靶场真实的Ip nmap -SP 192.168…

LingedList<T>,自定义泛型

LingedList<T>底层采用双向链表数据结构实现的集合(容器)。 数据结构:是计算机在内存中组织数据的一种方式。 分类: 线性数据结构: 数组:存储同类型数据的大小固定的集合。 列表(List):动态大小的数组,可以灵活的添加,删除元素。 链表(LinkedList):分…

目标检测 DN-DETR(2022)

文章目录 前言gt labels 和gt boxes加噪query的构造attention maskIS&#xff08;InStability&#xff09;指标 前言 gt labels 和gt boxes加噪 query的构造 attention mask IS&#xff08;InStability&#xff09;指标

媒界:家庭出行不用愁 江铃集团新能源易至EV3青春版值得拥有

随着家庭代步、接送孩子上下学的需求进一步释放&#xff0c;纯电小车市场迎来火热发展机遇。江铃集团新能源旗下的易至EV3青春版&#xff0c;以其灵动的车身设计、宽敞的内部空间以及先进的智能配置&#xff0c;成为了家庭用车的优质选择。 作为电动汽车和出行普及者&#xff0…

阿里面试: RocketMQ如何实现每秒上十万QPS的超高吞吐量读取的?

这玩意儿表面看上去挺牛逼&#xff0c;但其实背后的逻辑和套路&#xff0c;在咱们开发里见过的那些招数&#xff0c;都能找到影子。 今天小北和大家一起系统化的梳理梳理一遍&#xff0c;让大家功力猛增&#xff0c;吊打面试官。 1. 消息存储&#xff1a;巧妙利用顺序写 先说…

ARTS Week 43

Algorithm 本周的算法题为 1822. 数组元素积的符号 已知函数 signFunc(x) 将会根据 x 的正负返回特定值&#xff1a; 如果 x 是正数&#xff0c;返回 1 。 如果 x 是负数&#xff0c;返回 -1 。 如果 x 是等于 0 &#xff0c;返回 0 。 给你一个整数数组 nums 。令 product 为数…

SimpleFoc以及SVPWM学习补充记录

SimpleFoc SimpleFOC移植STM32&#xff08;一&#xff09;—— 简介 FOC控制的过程是这样的&#xff1a; 对电机三相电流进行采样得到 Ia,Ib,Ic。将 Ia,Ib,Ic 经过Clark变换得到 I_alpha I_beta。将 I_alpha I_beta 经过Park变换得到 Id,Iq。计算 Id,Iq 和其设定值 Id_ref 和…

Spring JDBC - Spring JDBC模版使用

前言 Spring JdbcTemplate是Spring Framework提供的一个强大的数据库访问工具&#xff0c;它简化了数据库操作的过程&#xff0c;为开发者提供了一个高级的数据库访问抽象层。 JdbcTemplate是Spring JDBC模块中的一个核心类&#xff0c;它位于org.springframework.jdbc.core包中…

开源项目都是怎么推广的?

大家好&#xff0c;我是爱折腾的刘大逵。跟我接触过的技术们都知道&#xff0c;一年一年的都在折腾着做一些项目&#xff0c;年年有进步&#xff0c;年年有想法&#xff0c;年年在折腾。今天给大家分享GITEE如何上推荐&#xff01; GITEE推荐有什么用&#xff1f; 众所周知&a…

C++版iwanna2

第二篇目录 程序的流程图程序游玩的效果下一篇博客要说的东西 程序的流程图 #mermaid-svg-lFW0ZjCdi5Xvl3gE {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-lFW0ZjCdi5Xvl3gE .error-icon{fill:#552222;}#mermaid-s…