JUC(Java.util.concurrent)的常见类

目录

♫ReentrantLock

♪什么是ReentrantLock

♪ReentrantLock的用法

♪ReentrantLock和synchronized的区别

♫Semaphore

♪什么是Semaphore

♪semaphore的用法

♫CountDownLatch

♪什么是CountDownLatch

♪CountDownLatch的使用

♫多线程环境使用ArrayList

♫多线程环境使用队列

♫多线程环境使用哈希表


JUC除了提供前面介绍过的线程池、定时器,还提供了多线程编程中其它一些常用的工具类和接口(ReentrantLock、Semaphore、CountDownLatch等)

♫ReentrantLock

♪什么是ReentrantLock

ReentrantLock 是 Java 标准库提供的一种可重入互斥锁 synchronized 定位类似,都是用来实现互斥效果,保证线程安全的。

♪ReentrantLock的用法

使用 ReentrantLock 需要使用  lock()  加锁, 如果获取不到锁就死等)或  trylock(超时时间)加锁, 如果获取不到锁, 等待一定的时间之后就放弃加锁)和  unlock()解锁)对代码块进行加锁解锁:
.
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
//加锁内容
reentrantLock.unlock();

为了避免加锁内容提前退出(有return语句或异常),导致没有执行到 unlock() 语句,一般搭配 try-finally 语句执行加锁加锁操作:

ReentrantLock reentrantLock = new ReentrantLock();
try {reentrantLock.lock();//加锁内容
} finally {reentrantLock.unlock();
}

♪ReentrantLock和synchronized的区别

. synchronized 是一个关键字, JVM 内部实现的 ( 大概率是基于 C++ 实现 );ReentrantLock 是标准库的一个类, JVM 外实现的 ( 基于 Java 实现 )。
. synchronized 使用时不需要手动释放锁; ReentrantLock 使用时需要手动释放。
. synchronized 在申请锁失败时, 会死等; ReentrantLock 可以通过 trylock 的方式等待一段时间就放弃。
. synchronized 是非公平锁; ReentrantLock 默认是非公平锁,也 可以通过构造方法传入一个 true 开启公平锁模式。
. synchronized 是通过 Object wait / notify 实现等待 - 唤醒, 每次唤醒的是一 个随机等待的线程;  ReentrantLock 搭配 Condition 类实现等待 - 唤醒, 可以更精确控制唤醒某个指 定的线程。

♫Semaphore

♪什么是Semaphore

Semaphore 是信号量的意思,用来表示 "可用资源的个数",其本质上就是一个计数器。

例如:图书馆有500个空位,学生扫码入座,可用座位-1(相当于信号量的P操作),学生扫码离座,可用座位+1(相当于信号量的V操作),如果座位为0,就无法再扫码入座了(阻塞等待)。

注:Semaphore 的 PV 操作中的加减计数器操作都是原子的,可以在多线程环境下直接使用

♪semaphore的用法

semaphore 通过传递的参数确定总资源个数,通过 acquire() 方法申请资源(P操作),通过release() 方法释放资源(V操作):

import java.util.concurrent.Semaphore;public class Test {public static void main(String[] args) {//初始值为3的信号量Semaphore semaphore = new Semaphore(3);Runnable runnable = new Runnable() {@Overridepublic void run() {try {//申请资源semaphore.acquire();Thread.sleep(100);//释放资源semaphore.release();} catch (InterruptedException e) {throw new RuntimeException(e);}}};//10个线程都尝试获取资源for (int i = 0; i < 10; i++) {Thread thread = new Thread(runnable);thread.start();}}
}

♫CountDownLatch

♪什么是CountDownLatch

CountDownLatch 用于同时等待 N 个任务执行结束, 好像跑步比赛,10个选手依次就位,哨声响才同时出发;所有选手都通过终点,才能公布成绩。

♪CountDownLatch的使用

CountDownLatch   通过传递参数确认需要完成的 任务个数,每个任务执行完毕, 都调用 countDown() 方法,在 CountDownLatch 内部的计数器同时自减,主线程中使用 await(),只有当计数器减为0时调用 countDown() 方法才会唤醒await():
import java.util.concurrent.CountDownLatch;public class Test {public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(10);Runnable runnable = new Runnable() {@Overridepublic void run() {try {Thread.sleep(100);countDownLatch.countDown();} catch (InterruptedException e) {throw new RuntimeException(e);}}};for (int i = 0; i < 10; i++) {Thread thread = new Thread(runnable);thread.start();}countDownLatch.wait();}
}

♫多线程环境使用ArrayList

在多线程环境下,直接使用ArrayList往往会出现线程安全问题,我们可以通过一下几点方案解决该问题:

♩.自己使用同步机制(synchronized 或者 ReentrantLock)进行加锁

♩.使用Collections.synchronizedList(new ArrayList) synchronizedList 是标准库提供的一个基于 synchronized 进行线程同步的 List,synchronizedList 的关键操作上都带有 synchronized。
.使用 CopyOnWriteArrayList
CopyOnWrite容器即写时拷贝的容器,当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行拷贝, 复制出一个新的容器,然后在新的容器里添加元素,
添加完元素之后,再将原容器的引用指向新的容器。 这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

♫多线程环境使用队列

.ArrayBlockingQueue :基于数组实现的阻塞队列
.LinkedBlockingQueue :基于链表实现的阻塞队列
.PriorityBlockingQueue :基于堆实现的带优先级的阻塞队列
.TransferQueue :最多只包含一个元素的阻塞队列

♫多线程环境使用哈希表

 HashMap 本身不是线程安全的,在多线程环境下使用哈希表可以使用Hashtable和ConcurrentHashMap。

♩.Hashtable:只是简单的把关键方法加上了 synchronized 关键字,一个Hashtable只有一把锁,两个线程访问Hashtable中的任何数据都会出现锁竞争。

.ConcurrentHashMap

ConcurrentHashMap 相比于 Hashtable 做出了一系列的改进和优化,大大缩小了锁冲突的概率(把一大锁转换成好几把小锁)。
①. ConcurrentHashMap的做法是对每个链表分别进行加锁,这样子操作不同链表里的元素就不会发生锁冲突, 大大降 低了锁冲突的概率。
②. ConcurrentHashMap对读操作不加锁,而是 使用了 volatile 保证从内存读取结果,避免了读和写之间读到写了一半的数据。
③. ConcurrentHashMap充分利用 CAS 特性( 比如 size 属性通过 CAS 来更新), 避免出现重量级锁的情况。
④. ConcurrentHashMap优化了扩容方式,即化整为零:发现需要扩容的线程,只需要创建一个新的数组, 同时只搬几个元素过去,扩容期间, 新老数组同时存在,后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程, 每个操作负责搬运一小部分元素,搬完最后一个元素再把老数组删掉。这个期间, 插入只往新数组加, 查找需要同时查新数组和老数组。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第13周 预习、实验与作业:Java网络编程

目录 1 课前问题列表 1.编写一个网络程序&#xff0c;为了与其他网络程序通信&#xff0c;至少要知道对方的什么信息&#xff1f; 2.TCP与UDP协议有什么不同的呢&#xff1f;什么时候该选择哪种协议&#xff1f;HTTP使用的是TCP还是UDP&#xff1f;不重要的短信息传送之类的功能…

【每日一题】子数组的最小值之和

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;贡献法单调栈 写在最后 Tag 【贡献法】【单调栈】【数组】【2023-11-27】 题目来源 907. 子数组的最小值之和 题目解读 计算整数数组的连续子数组中最小值的和。 解题思路 本题朴素的解决思想是求出所有的连续子数组…

MySQL使用函数和存储过程实现:向数据表快速插入大量测试数据

实现过程 1.创建表 CREATE TABLE user_info (id INT(11) NOT NULL AUTO_INCREMENT,name VARCHAR(20) DEFAULT NULL,age INT(3) DEFAULT NULL,pwd VARCHAR(20) DEFAULT NULL,phone_number VARCHAR(11) DEFAULT NULL,email VARCHAR(255) DEFAULT NULL,address VARCHAR(255) DEF…

Aapche Dubbo 不安全的 Java 反序列化 (CVE-2019-17564)

漏洞描述 Apache Dubbo 是一个高性能的、基于 Java 的开源 RPC 框架。 Apache Dubbo 支持不同的协议&#xff0c;它的 HTTP 协议处理程序是 Spring Framework 的 .org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter Spring Framework 的安全警告显示&am…

涵盖多种功能,龙讯旷腾Module第一期:物质结构

Module是什么 在PWmat的基础功能上&#xff0c;我们针对用户的使用需求开发了一些顶层模块&#xff08;Module&#xff09;。这些Module中的一部分是与已有的优秀工具的接口&#xff0c;一部分是以PWmat的计算结果为基础得到实际需要的物理量&#xff0c;一部分则是为特定的计…

利用STM32和蓝牙模块构建智能物联网设备的开发指南

智能物联网设备在现代生活中扮演着重要的角色&#xff0c;而STM32微控制器和蓝牙模块则为实现智能物联网设备提供了基础支持。本文将介绍如何使用STM32微控制器和蓝牙模块构建智能物联网设备的开发指南&#xff0c;包括硬件设计、蓝牙模块配置、传感器数据采集和云平台连接等关…

Java 之 lambda 表达式(二)---- Stream 操作 API

目录 一. 前言 二. Stream 创建 2.1. 使用集合来创建 Stream 2.2. 使用数组创建 Stream 2.3. 由值创建 Stream 2.4. 由函数创建无限流 Stream 2.5. 代码示例 三. Stream 操作 3.1. 中间型操作 3.1.1. filter() 3.1.2. map() 3.1.3. mapToInt()、mapToLong()、mapTo…

Docker Swarm总结+service创建和部署、overlay网络以及Raft算法(2/5)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

云原生CI/CD流水线发布

文章目录 前言k8s组件与操作流程k8s组件创建pod k8s代码&&打包k8s yamldeploymentservicek8s volumesdemo CIgitlabCI runner CD配置git repository安装argo创建argo cd的配置yamlargocd和helm结合argocd hookargocd 发布 RBACoperatorhelmprometheus && grafn…

【Python】plt库详解和示例

plt 是 Python 中 Matplotlib 库的一个常用别名&#xff0c;它表示 pyplot&#xff0c;这是一个用于创建图形和图形的可视化表示的工具。下面是一些 plt 函数的详解和示例&#xff0c;以帮助大家理解和使用。 目录 plt.subplots&#xff08;&#xff09;plt.savefig&#xff0…

Milvus入门手册1.0

一、window环境搭建&#xff08;单机&#xff09; 1、docker安装 略 2、milvus安装 参考文档&#xff1a;https://milvus.io/docs/install_standalone-docker.md tips: &#xff08;1&#xff09;compose.yaml下载比较慢&#xff0c;可以在网络上找一份。 &#xff08;2&…

「琥珀黄」农产品销售运营大屏助力农产品销售改革

农业作为国家经济的重要支柱产业&#xff0c;农产品销售一直备受关注。农产品销售一直是农业行业关注的焦点之一。随着科技进步和市场竞争的加剧&#xff0c;传统的销售方式面临着新的挑战。为了让农产品销售实现腾飞&#xff0c;我们需要打破传统&#xff0c;采用新的销售策略…