【JavaEE】JUC(Java.util.concurrent)常见类

文章目录
- 前言
- ReentrantLock
- 原子类
- 线程池
- 信号量
- CountDownLatch
- 相关面试题
前言
经过前面文章的学习我们大致了解了如何实现多线程编程和解决多线程编程中遇到的线程不安全问题,java.util.concurrent 是我们多线程编程的一个常用包,那么今天我将为大家分享 java.util.concurrent 包下的其他几种常见的类。
ReentrantLock
ReentrantLock 是可重入互斥锁,跟 synchronized 定位是类似的,都是用来保证线程安全的,但是 ReentrantLock 在某些方面相较于 synchronized 有突出的优势。
ReentrantLock 的加锁方式分为两种:
- lock():如果获取不到锁,线程就会进入阻塞等待状态
- tryLock():如果获取不到锁,就会放弃加锁,而不是进入阻塞等待状态
使用 ReentrantLock 的时候需要手动 unLock() 解锁,如果忘记了手动解锁这个操作,将会带来比较严重的后果。
所以为了解决有些时候忘记手动解锁的情况,往往需要借助 try-finally 来进行解锁操作。
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {//working
}finally {lock.unlock();
}
ReentranLock 与 synchronized 相比的优势
-
ReentrantLock 在加锁的时候,有两种方式,lock() 和tryLock()。使用 lock() 的时候,如果未获取到锁就会进入阻塞等待状态,而使用 tryLock() 的话,如果没有获取到锁就会放弃获取,而不是进入阻塞等待
-
ReentrantLock 提供了公平锁的实现(默认情况下是非公平锁)
-
ReentranLock 提供了更强大的等待通知机制,搭配了Condition类,实现等待通知,可以指定唤醒某个线程
如何选择使用哪个锁?
- 锁竞争不激烈的时候, 使用 synchronized, 效率更高, 自动释放更方便.
- 锁竞争激烈的时候, 使用 ReentrantLock, 搭配 trylock 更灵活控制加锁的行为, 而不是死等.
- 如果需要使用公平锁, 使用 ReentrantLock.
通常情况下还是建议使用 synchronized,虽然 ReentrantLock 在某些方面具有优势,但是使用起来较麻烦,并且Java程序员在 synchronized 里面做了很多的优化。
原子类
原子类内部都是使用 CAS 操作实现的,因为 CAS 操作时原子性的,不需要进行加锁操作,所以性能要比加锁好很多。
- AtomicBoolean
- AtomicInteger
- AtomicIntegerArray
- AtomicLong
- AtomicReference
- AtomicStampedReference
原子类常见方法:
- addAndGet(int delta); —— i += delta;
- decrementAndGet(); —— --i;
- getAndDecrement(); —— i–;
- incrementAndGet(); —— ++i;
- getAndIncrement(); —— i++;
CAS 操作我在前面详细讲解过,大家想要了解的话可以去看看。CAS(Compare And Swap)操作
线程池
线程池是为了解决因线程频繁创建和销毁而造成的资源浪费问题。
使用线程池需要使用到 ExecutorService 和 Executors 两个类。
ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}
});
- ExecutorService 表示一个线程池实例.
- Executors 是一个工厂类, 能够创建出几种不同风格的线程池.
- ExecutorService 的 submit 方法能够向线程池中提交若干个任务
Executors 创建线程池的几种方式
- newFixedThreadPool: 创建固定线程数的线程池
- newCachedThreadPool: 创建线程数目动态增长的线程池.
- newSingleThreadExecutor: 创建只包含单个线程的线程池.
- newScheduledThreadPool: 设定 延迟时间后执行命令,或者定期执行命令. 是进阶版的 Timer。
这里面也涉及到了工厂模式,大家可以去看看这篇文章了解一下【JavaEE】多线程案例-线程池
信号量
信号量(Semaphore)是一种实现任务间通信的机制,可以用于实现任务之间的同步或临界资源的互斥访问。它通常被用于协助一组相互竞争的任务来访问临界资源。
信号量是一个非负整数,获取信号量的任务会将该整数减1。当信号量为0时,所有试图获取该信号量的任务都将处于阻塞状态。信号量的值代表积累下来的释放信号量操作的次数。
申请资源的操作被称为 P 操作,释放资源的操作被称为 V 操作。
信号量可以分为二值信号量和计数信号量两种。二值信号量只有一个消息队列,队列有两种状态:空或满。而计数信号量可以看做长度大于1的消息队列,用于计数。信号量的计数值表示还有多少个事件未被处理。当某个事件发生时,任务或中断会释放一个信号量(将信号量计数值加1);当需要处理某个事件时,任务或中断会取走一个信号量(将信号量计数值减1)。
加锁和解锁的操作就可以看成是二值信号量的操作,当加锁的时候信号量就为0,释放锁的时候信号量就为1.
在Java代码中,信号量相关的操作被封装在 Semaphore 类中,acquire() 方法表示申请资源,release() 方法表示释放资源。
public class Test2 {public static void main(String[] args) throws InterruptedException {Semaphore semaphore = new Semaphore(4);semaphore.acquire();System.out.println("获取资源");semaphore.acquire();System.out.println("获取资源");semaphore.acquire();System.out.println("获取资源");semaphore.acquire();System.out.println("获取资源");semaphore.acquire();System.out.println("获取资源");semaphore.release();System.out.println("释放资源");}
}

当申请的资源量大于总的资源量的时候,线程就会进入阻塞等待状态,直到其他线程释放掉部分信号量。
CountDownLatch
CountDownLatch是Java中的一个同步工具类,用来协调多个线程之间的同步。它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
CountDownLatch通过一个计数器来实现这个功能,计数器的初始值通常设置为需要等待完成的线程数量。每当一个线程完成了自己的任务,计数器的值就会减1。当计数器的值达到0时,表示所有线程都已经完成任务,此时在CountDownLatch上等待的线程就可以恢复执行。
CountDownLatch可以用来确保某些活动在其他活动完成之前不会继续执行。例如,可以确保某个计算在其需要的所有资源都被初始化之后才继续执行,或者确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
在Java中,可以使用CountDownLatch的countDown()方法来对计数器做减操作,就是告诉CountDownLatch我这个当前的任务完成了,使用await()方法等待计数器达到0。所有调用await()方法的线程都会被阻塞,直到计数器达到0或者等待线程被中断或者超时。
public class Demo2 {private static int count;public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(10);for(int i = 0; i < 10; i++) {Thread t = new Thread(() -> {try {Thread.sleep((long)(Math.random() * 4000));System.out.println(++count + "号完成比赛");countDownLatch.countDown();} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}countDownLatch.await();System.out.println("结束比赛");}
}

只有调用了10次 countDown() 方法之后,await() 方法才会结束等待,继续执行后面的代码。
需要注意的是,CountDownLatch是一次性的,一旦计数器的值达到0,就不能再次使用。如果需要多次使用类似的功能,可以考虑使用CyclicBarrier等其他同步工具类。
相关面试题
1) 线程同步的方式有哪些?
synchronized, ReentrantLock, Semaphore 等都可以用于线程同步.
2) 为什么有了 synchronized 还需要 juc 下的 lock?
以 juc 的 ReentrantLock 为例,
- synchronized 使用时不需要手动释放锁. ReentrantLock 使用时需要手动释放. 使用起来更灵活,
- synchronized 在申请锁失败时, 会死等. ReentrantLock 可以通过 trylock 的方式等待一段时间就放弃.
- synchronized 是非公平锁, ReentrantLock 默认是非公平锁. 可以通过构造方法传入一个 true 开启公平锁模式.
- synchronized 是通过 Object 的 wait / notify 实现等待-唤醒. 每次唤醒的是一个随机等待的线程. ReentrantLock 搭配 Condition 类实现等待-唤醒, 可以更精确控制唤醒某个指定的线程.
3) AtomicInteger 的实现原理是什么?
基于 CAS 机制. 伪代码如下:
class AtomicInteger {private int value;public int getAndIncrement() {int oldValue = value;while ( CAS(value, oldValue, oldValue+1) != true) {oldValue = value;}return oldValue;}
}
4) 信号量听说过么?之前都用在过哪些场景下?
信号量, 用来表示 “可用资源的个数”. 本质上就是一个计数器.
使用信号量可以实现 “共享锁”, 比如某个资源允许 3 个线程同时使用, 那么就可以使用 P 操作作为加锁, V 操作作为解锁, 前三个线程的 P 操作都能顺利返回, 后续线程再进行 P 操作就会阻塞等待,直到前面的线程执行了 V 操作
相关文章:
【JavaEE】JUC(Java.util.concurrent)常见类
文章目录 前言ReentrantLock原子类线程池信号量CountDownLatch相关面试题 前言 经过前面文章的学习我们大致了解了如何实现多线程编程和解决多线程编程中遇到的线程不安全问题,java.util.concurrent 是我们多线程编程的一个常用包,那么今天我将为大家分…...
清除浮动的方法
为什么需要清除浮动? 父级的盒子不能把height定死这样,浮动子类就没有了(行内块元素的特点),父类高度为零。故引用清除浮动 1、父级没有高度 2、子盒子浮动了 3、影响下面的布局了,我们就应该清除浮动了…...
LangChain 摘要 和问答示例
在Azure上的OpenAI端点 注意 OpenAI key 可以用微软 用例【1. 嵌入 ,2. 问答】 1. import os import openai from langchain.embeddings import OpenAIEmbeddings os.environ["OPENAI_API_KEY"] "****" # Azure 的密钥 os.environ["OP…...
(32)测距仪(声纳、激光雷达、深度摄影机)
文章目录 前言 32.1 单向测距仪 32.2 全向性近距离测距仪 32.3 基于视觉的传感器 前言 旋翼飞机/固定翼/无人车支持多种不同的测距仪,包括激光雷达(使用激光或红外线光束进行距离测量)、360 度激光雷达(可探测多个方向的障碍…...
教你拥有一个自己的QQ机器人!0基础超详细保姆级教学!基于NoneBot2 Windows端搭建QQ机器人
0.序言 原文链接:教你本地化部署一个QQ机器人本教程主要面向Windows系统用户教程从0开始全程详细指导,0基础萌新请放心食用🍕如果你遇到了问题,请仔细检查是否哪一步有遗漏。如果你确定自己的操作没问题,可以到原文链…...
智能银行卡明细筛选与统计,轻松掌握账户总花销!
作为现代生活的重要组成部分,银行卡成为了我们日常消费和收入的主要途径。但是,当我们需要了解自己的银行卡账户的总花销时,繁琐的明细筛选和统计工作常常让人头疼。现在,让我们向您推荐一款智能银行卡明细筛选与统计工具…...
SRT服务器SLS
目前互联网上的视频直播有两种,一种是基于RTMP协议的直播,这种直播方式上行推流使用RTMP协议,下行播放使用RTMP,HTTPFLV或者HLS,直播延时一般大于3秒,广泛应用秀场、游戏、赛事和事件直播,满足了…...
Linux 安装 Android SDK
先安装jdk RUN apt-get install default-jdk 参考:http://t.zoukankan.com/braveym-p-6143356.html mkdir -p $HOME/install/android-sdk wget https://dl.google.com/android/repository/commandlinetools-linux-9123335_latest.zip unzip commandlinetools-linu…...
【QT开发笔记-基础篇】| 第四章 事件QEvent | 4.4 鼠标按下、移动、释放事件
本章要实现的整体效果如下: QEvent::MouseButtonPress 鼠标按下时,触发该事件,它对应的子类是 QMouseEvent QEvent::MouseMove 鼠标移动时,触发该事件,它对应的子类是 QMouseEvent QEvent::MouseButtonRel…...
vue3父子通信+ref,toRef,toRefs使用实例
ref是什么? 生成值类型的响应式数据可用于模板和reactive通过.value修改值可以获取DOM元素 <p ref”elemRef”>{{nameRef}} -- {{state.name}}</p> // 获取dom元素 onMounted(()>{ console.log(elemRef.value); }); toRef是什么? 针对一个响应式对象(rea…...
输入电压转化为电流性 5~20mA方案
输入电压转化为电流性 5~20mA方案 方案一方案二方案三 方案一 XTR111是一款精密的电压-电流转换器是最广泛应用之一。原因有二:一是线性度非常好、二是价格便宜。总结成一点,就是性价比高。 典型电路 最终电路 Z1二极管处输出电流表达式:…...
SpringBoot自带模板引擎Thymeleaf使用详解①
目录 前言 一、SpringBoot静态资源相关目录 二、变量输出 2.1 在templates目录下创建视图index.html 2.2 创建对应的Controller 2.3 在视图展示model中的值 三、操作字符串和时间 3.1 操作字符串 3.2 操作时间 前言 Thymeleaf是一款用于渲染XML/HTML5内容的模板引擎&am…...
推荐算法——Apriori算法原理
0、前言: 首先名字别读错:an pu ruo ao rui 【拼音发音】Apriori是一种推荐算法推荐系统:从海量数据中,帮助用户进行信息的过滤和选择。主要推荐方法有:基于内容的推荐、协同过滤推荐、基于关联规则的推荐、基于知识的…...
vue ant 隐藏 列
vue ant 隐藏 列 如果你使用的是Vue和Ant Design Vue组件库,你可以使用v-if指令来实现条件渲染来隐藏列。以下是一个示例代码: <template><a-table :columns"columns" :data-source"data"><template v-slot:custom…...
java基础之初始化顺序
初始化顺序 在类中变量定义的顺序决定了它们初始化的顺序。在创建任何java对象时,都是依次调用父类非静态初始化块、父类构造器执行初始化、本类的非静态初始化块、本类构造器执行初始化 public class House { // 构造器之前 Window w1 new Window(1); Ho…...
FFmpeg 命令:从入门到精通 | ffmpeg filter(过滤器 / 滤镜)
FFmpeg 命令:从入门到精通 | ffmpeg filter(过滤器 / 滤镜) FFmpeg 命令:从入门到精通 | ffmpeg filter(过滤器 / 滤镜)ffmpeg fliter 基本内置变量视频裁剪文字水印图片水印画中画视频多宫格处理 FFmpeg 命…...
【C语言】23-结构体类型
目录 1. 如何建立结构体类型2. 如何使用结构体2.1 定义结构体变量2.2 结构体变量的初始化和引用2.3 结构体数组2.4 结构体指针2.4.1 指向结构体变量的指针2.4.2 指向结构体数组的指针C 语言提供了一些由系统已定义好的数据类型,如: int、 float、 char 等,用户可以在程序…...
Python小技巧:快速合并字典dict()
文章目录 前言知识点字典合并1. dict.update()基础合并2. 字典推导式 update() 后话 前言 这里是Python小技巧的系列文章。这是第四篇,快速合并字典。 在Python的使用中,有时候需要将两个 dict(字典) 进行合并。 通常我们会借助 dict(字典) 的内置方法 …...
如何使用 React 和 Docusaurus 编写的一些自定义钩子(Hook)
import useRouteContext from @docusaurus/useRouteContext; import {DependencyList, useEffect, useRef, useState, useMemo } from react; import {dequal } from dequal; /* eslint-disable global-require */ // @ts-ignore/*** 用于深度检测依赖的useMemo钩子* @param fa…...
【初识Linux】Linux环境配置、Linux的基本指令 一
Linux基本指令一 一、学习前提(环境配置)①安装Xshell和云服务器推荐②Xshell用途如下图③打开Xshell 二、 Linux基本指令①whoami和who指令②pwd、ls、ls -l三个指令ls指令扩充 ③cd指令前提了解有了上面的认识,我们就可以开始cd指令的学习了 ④tree指令…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
