Java并发(十五)Java并发工具类

news2024/11/17 6:48:21

CountDownLatch

字面意思为 递减计数锁。用于控制一个线程等待多个线程。
**CountDownLatch**** 维护一个计数器 count,表示需要等待的事件数量。**countDown 方法递减计数器,表示有一个事件已经发生。调用 await 方法的线程会一直阻塞直到计数器为零,或者等待中的线程中断,或者等待超时。
QQ_1722344822965.png
CountDownLatch 是基于 AQS(AbstractQueuedSynchronizer) 实现的。
CountDownLatch 唯一的构造方法:

// 初始化计数器
public CountDownLatch(int count) {};

说明:

  • count 为统计值。

CountDownLatch 的重要方法:

public void await() throws InterruptedException { };
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
public void countDown() { };

说明:

  • await() - 调用 await() 方法的线程会被挂起,它会等待直到 count 值为 0 才继续执行。
  • await(long timeout, TimeUnit unit) - 和 await() 类似,只不过等待一定的时间后 count 值还没变为 0 的话就会继续执行
  • countDown() - 将统计值 count 减 1

示例:

public class CountDownLatchDemo {

    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(2);

        new Thread(new MyThread(latch)).start();
        new Thread(new MyThread(latch)).start();

        try {
            System.out.println("等待2个子线程执行完毕...");
            latch.await();
            System.out.println("2个子线程已经执行完毕");
            System.out.println("继续执行主线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static class MyThread implements Runnable {

        private CountDownLatch latch;

        public MyThread(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            System.out.println("子线程" + Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕");
            latch.countDown();
        }

    }

}

CyclicBarrier

字面意思是 循环栅栏。**CyclicBarrier**** 可以让一组线程等待至某个状态(遵循字面意思,不妨称这个状态为栅栏)之后再全部同时执行**。之所以叫循环栅栏是因为:当所有等待线程都被释放以后,CyclicBarrier 可以被重用。
CyclicBarrier 维护一个计数器 count。每次执行 await 方法之后,count 加 1,直到计数器的值和设置的值相等,等待的所有线程才会继续执行。
CyclicBarrier 是基于 ReentrantLockCondition 实现的。
CyclicBarrier 应用场景:CyclicBarrier 在并行迭代算法中非常有用。
QQ_1722345279758.png
CyclicBarrier 提供了 2 个构造方法

public CyclicBarrier(int parties) {}
public CyclicBarrier(int parties, Runnable barrierAction) {}

说明:

  • parties - parties 数相当于一个阈值,当有 parties 数量的线程在等待时, CyclicBarrier 处于栅栏状态。
  • barrierAction - 当 CyclicBarrier 处于栅栏状态时执行的动作。

CyclicBarrier 的重要方法:

public int await() throws InterruptedException, BrokenBarrierException {}
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {}
// 将屏障重置为初始状态
public void reset() {}

说明:

  • await() - 等待调用 await() 的线程数达到屏障数。如果当前线程是最后一个到达的线程,并且在构造函数中提供了非空屏障操作,则当前线程在允许其他线程继续之前运行该操作。如果在屏障动作期间发生异常,那么该异常将在当前线程中传播并且屏障被置于断开状态。
  • await(long timeout, TimeUnit unit) - 相比于 await() 方法,这个方法让这些线程等待至一定的时间,如果还有线程没有到达栅栏状态就直接让到达栅栏状态的线程执行后续任务。
  • reset() - 将屏障重置为初始状态。

示例:

public class CyclicBarrierDemo {

    final static int N = 4;

    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(N,
          new Runnable() {
              @Override
              public void run() {
                  System.out.println("当前线程" + Thread.currentThread().getName());
              }
          });

        for (int i = 0; i < N; i++) {
            MyThread myThread = new MyThread(barrier);
            new Thread(myThread).start();
        }
    }

    static class MyThread implements Runnable {

        private CyclicBarrier cyclicBarrier;

        MyThread(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");
            try {
                Thread.sleep(3000); // 以睡眠来模拟写入数据操作
                System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕,等待其他线程写入完毕");
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }

    }

}

Semaphore

字面意思为 信号量。**Semaphore**** 用来控制某段代码块的并发数。**
Semaphore 管理着一组虚拟的许可(permit),permit 的初始数量可通过构造方法来指定。每次执行 acquire 方法可以获取一个 permit,如果没有就等待;而 release 方法可以释放一个 permit。
Semaphore 应用场景:

  • Semaphore 可以用于实现资源池,如数据库连接池。
  • Semaphore 可以用于将任何一种容器变成有界阻塞容器。

QQ_1722345428303.png
Semaphore 提供了 2 个构造方法:

// 参数 permits 表示许可数目,即同时可以允许多少线程进行访问
public Semaphore(int permits) {}
// 参数 fair 表示是否是公平的,即等待时间越久的越先获取许可
public Semaphore(int permits, boolean fair) {}

说明:

  • permits - 初始化固定数量的 permit,并且默认为非公平模式。
  • fair - 设置是否为公平模式。所谓公平,是指等待久的优先获取 permit。

Semaphore的重要方法:

// 获取 1 个许可
public void acquire() throws InterruptedException {}
//获取 permits 个许可
public void acquire(int permits) throws InterruptedException {}
// 释放 1 个许可
public void release() {}
//释放 permits 个许可
public void release(int permits) {}

说明:

  • acquire() - 获取 1 个 permit。
  • acquire(int permits) - 获取 permits 数量的 permit。
  • release() - 释放 1 个 permit。
  • release(int permits) - 释放 permits 数量的 permit。

示例:

public class SemaphoreDemo {

    private static final int THREAD_COUNT = 30;

    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);

    private static Semaphore semaphore = new Semaphore(10);

    public static void main(String[] args) {
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        System.out.println("save data");
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        threadPool.shutdown();
    }

}

总结

  • CountDownLatchCyclicBarrier 都能够实现线程之间的等待,只不过它们侧重点不同:
    • CountDownLatch 一般用于某个线程 A 等待若干个其他线程执行完任务之后,它才执行;
    • CyclicBarrier 一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
    • 另外,CountDownLatch 是不可以重用的,而 CyclicBarrier 是可以重用的。
  • Semaphore 其实和锁有点类似,它一般用于控制对某组资源的访问权限。

相关文章:https://dunwu.github.io/javacore/pages/02d274/#semaphore

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

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

相关文章

程序员如何准备既符合“八股文“又展现实力的面试?

在当今竞争激烈的IT行业中,面试已成为程序员求职路上的一道重要关卡。而在这个过程中,"八股文"这个词频频出现,引发了业内人士的热议。本文将深入探讨"八股文"在程序员面试中的角色,以及它对实际工作的影响。 目录 1. 程序员面试八股文的利弊分析什么是&q…

Unity 预制动态绑定光照贴图遇到变白问题

预制绑定光照贴图&#xff0c;网上解决方案很多&#xff0c;已下是要点&#xff1a; //烘培完场景之后&#xff0c;保存光照贴图信息 void StoreLightmapData() {lightMap.Clear();LightmapData[] lds LightmapSettings.lightmaps;foreach (LightmapData data in lds){Custom…

无人机之科学防汛篇

随着全球气候变化的加剧&#xff0c;极端天气时间频发&#xff0c;汛期防汛工作面临着前所未有的挑战。传统的防汛手段&#xff0c;如人工巡堤、地面监测等&#xff0c;在复杂多变的自然环境下显得力不从心。而无人机技术的快速发展&#xff0c;为科学防汛提供了新的解决方案。…

Java面试八股之Spring AOP 和 AspectJ AOP 的区别

Spring AOP 和 AspectJ AOP 的区别 Spring AOP 和 AspectJ AOP 是两种不同的面向切面编程&#xff08;Aspect-Oriented Programming, AOP&#xff09;实现。它们各有特点&#xff0c;适用于不同的场景。下面是一些主要的区别&#xff1a; 1. 实现机制 Spring AOP: 基于代理…

Python NLTK 情感分析不正确

1、问题背景 一位 Reddit 用户使用 Python 的 NLTK 库来训练一个朴素贝叶斯分类器以研究其他句子的情感&#xff0c;但是无论输入什么句子&#xff0c;分类器总是预测为正面。 2、解决方案 经过仔细检查&#xff0c;发现原始代码中的问题在于 wordList 为空。因此&#xff0…

【LLM】-12-部署Langchain-Chatchat-0.3.x版本

目录 1、0.3与0.2的功能对比 2、0.3.x支持多种部署方式 2.3、源码安装 2.3.1、项目源码下载 2.3.2、创建conda环境 2.3.3、安装poetry 2.3.4、安装依赖库 2.3.5、项目初始化 2.3.6、初始化知识库 2.3.7、启动服务 2.3.8、配置说明 2.3.8.1、basic_settings.yaml 2…

一副穿戴甲背后,5万苏北宝妈如何硬控全球美甲潮流?

2019年的一天&#xff0c;张达在拼多多后台看到一个有趣的订单。“看姓名、联系方式&#xff0c;像表妹下的订单&#xff0c;但我的穿戴甲店才开第二天&#xff0c;她应该不可能知道。”张达回忆。 1993年出生的张达&#xff0c;是江苏东海县人&#xff0c;当地以水晶闻名。高…

达梦数据库的系统视图v$bufferpool

达梦数据库的系统视图v$bufferpool 达梦数据库系统视图V$BUFFERPOOL的主要作用是监控和管理数据库缓冲池的性能。通过查询V$BUFFERPOOL视图&#xff0c;用户可以获取以下关键信息&#xff1a; 缓存命中率&#xff1a;显示缓冲池的命中率&#xff0c;即从缓冲池中成功获取数据的…

嵌入式☞第二组(壹)

C语言基础: 循环的构成&#xff1a; 循环体 循环条件 循环的分类&#xff1a; 无限循环&#xff1a;程序设计中尽量避免无限循环。(程序中的无限循环必须可控) 有限循环&#xff1a;循环限定循环次数或者循环的条件。 当型循环的实现&#xff1a; while 语法 while(循…

【MySQL】索引 【上】 {没有索引的查询/磁盘/mysql与磁盘IO/初识索引}

文章目录 1.没有索引存在的问题2. 认识磁盘MySQL与存储MySQL与磁盘交互基本单位建立共识图解IO认识索引 在关系数据库中&#xff0c;索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构&#xff0c;它是某个表中一列或若干列值的集合和相应的指向表中物…

初学Mybatis之缓存

所有的查询都需要连接数据库&#xff0c;而连接数据库消耗资源 我们可以把一次查询的结果暂时存在一个可以直接获取到的地方&#xff08;内存&#xff1a;缓存&#xff09; 我们再次查询相同数据的时候&#xff0c;直接走缓存&#xff0c;不走数据库 缓存&#xff1a;存在内…

3.5.1、查找和排序算法-算法介绍

算法特性 算法是对特定问题求解步骤的一种描述&#xff0c;它是指令的有限序列&#xff0c;其中每一条指令表示一个或多个操作。简单的说算法就是某个问题的解题思路&#xff0c;算法的五个重要特性如下&#xff1a; 有穷性。一个算法必须总是&#xff08;对任何合法的输入值…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十二章 设备树常用of函数

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

NAS变身云盘管理大师:群晖部署AList全攻略!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒🔑 AList功能简介🚀 快速部署📝 操作步骤🐳 Docker容器部署:灵活与强大📝 操作步骤📝 群晖部署🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 在这个数字化时代,我们似乎都不可避免地拥有多个…

【数据结构】:大厂面试经典链表OJ题目详解

反转链表 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 思路解透 本题就是通过不停地将最先的 head 节点位置的后一位插到最前面&#xff0c;完成链表的反转 本题需要两个节点变量 cur&#xff1a;其任务就是定位到原 head 节点位置的前一位&#xff0c;然后将自己…

列表(list)—python

一、列表的定义方式 列表内的每一个数据称为元素&#xff0c;列表以[ ]作为标识&#xff0c;列表内的每个元素之间用逗号隔开。 列表的基本语法如下&#xff1a; #字面量 [元素1,元素2,元素3,元素4,……]#定义变量 变量名称[元素1,元素2,元素3,元素4,……]#定义空列表 变量名…

Linux的防火墙

一、防火墙概述 防火墙是一种计算机硬件和软件的结合&#xff0c;使internet和intranet之间建立一个安全网关&#xff08;Security Gateway&#xff09;&#xff0c;从而保护内网免受非法用户侵入的技术。 防火墙主要由服务访问规则、验证工具、包过滤和应用网关4个部分组成。…

安防视频监控EasyCVR视频汇聚平台无法编辑设备通道信息的原因排查及解决

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台基于云边端一体化架构&#xff0c;兼容性强、支持多协议接入&#xff0c;包括国标GB/T 28181协议、部标JT808、GA/T 1400协议、RTMP、RTSP/Onvif协议、海康Ehome、海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石云SD…

ECharts - 坐标轴刻度数值处理

写图表时&#xff0c;Y轴的数值过大&#xff0c;不太可能直接展示&#xff0c;这时候就得简写了&#xff0c;或者百分比展示的也要处理&#xff0c;如下图&#xff1a; yAxis: {type: value,// Y轴轴线axisLine: { show: false }, // 刻度线axisTick: { show: false },// 轴刻度…

ECharts实现按月统计和MTBF统计

一、数据准备 下表是小明最近一年的旅游记录 create_datecity_namecost_money2023-10-10 10:10:10北京14992023-11-11 11:11:11上海29992023-12-12 12:12:12上海19992024-01-24 12:12:12北京1232024-01-24 12:12:12上海2232024-02-24 12:12:12广州5642024-02-24 12:12:12北京…