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.mzph.cn/news/177911.shtml

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

相关文章

数据分享 I 重点城市现状建筑数据,shp格式放送

数据名称: 现状建筑数据 数据格式: Shp 数据时间: 不同城市的数据时间有所不同&#xff0c;详情可搜“吧唧数据” 数据几何类型: 面 数据坐标系: WGS84坐标系 数据来源&#xff1a;网络公开数据 深圳市现状建筑数据示意图 东莞市部分镇街现状建筑数据示意图 武汉市部…

深入了解MySQL数据库管理与应用

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 当涉及MySQL数据库管理与应用时&#xff0c;深…

【Cisco Packet Tracer】构造超网

​​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《Cisco Packet Tracer | 奇遇记》⏰寄 语&#xff1a;风翻云浪激&#xff0c;剑舞星河寂。 临风豪情壮志在&#xff0c;拨云见日昂首立。 目录 ⛳️1. Cisco Packet Trace…

在数据库中进行表内容的修改(MYSQL)

根据表中内容&#xff0c;用命令语句创建数据库&#xff0c;表格&#xff0c;以及插入&#xff0c;修改&#xff0c;删除表格中的内容。 创建数据库&#xff1a;zrzy mysql> create database zrzy; 引用zrzy数据库&#xff1a; mysql> use zrzy; 创建student_info表&…

vulnhub靶机gigachad_vh

下载地址&#xff1a;Gigachad: 1 ~ VulnHub 主机发现 目标166 端口扫描 端口服务扫描 漏洞扫描 这玩意多得离谱 于是我用a重新扫了一遍 先去看web (⊙﹏⊙)离谱&#xff0c;目录扫描&#xff08;之前先去看一下nmap扫到的html&#xff09; 后面扫描的目录奇多&#xff0c;而…

NX二次开发UF_MTX3_x_vec 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_MTX3_x_vec Defined in: uf_mtx.h void UF_MTX3_x_vec(const double mtx [ 9 ] , double x_vec [ 3 ] ) overview 概述 Returns the X-direction vector of a matrix. 返回矩阵…

uniapp地图基本使用及解决添加markers不生效问题?

uniapp地图使用 App端 通过 nvue 页面实现地图 文章目录 uniapp地图使用效果图templatejs添加 marker使用地图查看位置移到到当前位置 效果图 template <template><view class"mapWrap"><!-- #ifdef APP-NVUE --><map class"map-containe…

springboot自定义更换启动banner动画

springboot自定义更换启动banner动画 文章目录 springboot自定义更换启动banner动画 &#x1f4d5;1.新建banner&#x1f5a5;️2.启动项目&#x1f516;3.自动生成工具&#x1f9e3;4.彩蛋 &#x1f58a;️最后总结 &#x1f4d5;1.新建banner 在resources中新建banner.txt文…

my.ini添加了一句后又删除了,重启却失败的解决办法

背景&#xff1a;添加了一句&#xff0c;然后保存了&#xff0c;之后打开删掉了&#xff0c;结果就无法启动了&#xff0c;最后另存为ANSI格式&#xff0c;再把这个格式文件覆盖my.ini即可解决

商品软文怎么写?媒介盒子教你三步

想要把产品卖出去&#xff0c;除了保证产品质量外&#xff0c;还可以通过线上推广来提高产品销量&#xff0c;而商品文案就是线上推广中的重要因素&#xff0c;今天媒介盒子就来和大家聊聊&#xff0c;怎么写好商品软文。 商品软文想要写好主要分为三要素&#xff1a;痛点、卖…

C++相关闲碎记录(1)

1、C绘制爱心图像 #include <iostream> #include <cmath>using namespace std;int main() {// 心形曲线公式 (x^2 y^2 - a)^3 - x^2*y^3 0double a 1;double bound 1.5 * sqrt(a);double step 0.05;for (double y bound; y > -bound; y - step) {for (do…

GAN:GAN论文学习

论文&#xff1a;https://arxiv.org/pdf/1406.2661.pdf 发表&#xff1a;2014 一、GAN简介&#xff1a;Generative Adversarial Network GAN是由Ian Goodfellow于2014年提出&#xff0c;GAN&#xff1a;全名叫做生成对抗网络。GAN的目的就是无中生有&#xff0c;以假乱真。 …

3. 迷宫问题

一.题干 迷宫有一个入口&#xff0c;一个出口。一个人从入口走进迷宫&#xff0c;目标是找到出口。阴影部分和迷宫的外框为墙&#xff0c;每一步走一格&#xff0c;每格有四个可走的方向&#xff0c;探索顺序为地图方向&#xff1a;南&#xff08;下&#xff09;、东&#xff0…

【Qt】之QSet使用

描述 QSet类是一个模板类&#xff0c;它提供基于散列表的集合。 QSet是Qt的通用容器类之一。它以未指定的顺序存储值&#xff0c;并提供非常快速的值查找。在内部,QSet是作为QHash实现的。 下面是一个带有QString值的QSet示例: QSet<QString> set;插入方式1&#xff…

Java学习路线第二篇:Java Web

这篇则分享Java学习路线第二part&#xff1a;Java Web 恭喜你已经成功追到第二章节啦&#xff0c;要被自己的努力感动到了吧&#xff0c;而这节将承担起学完Java web 的使命&#xff0c;本使命为单向契约&#xff0c;你可选择YES或者选择YES。 HTMLCSSJavaScript(JS) 【动…

MySQL 高可用架构

MySQL 是实际生产中最常用的数据库&#xff0c;生产环境数据量极为庞大&#xff0c;对性能和安全要求很高&#xff0c;单机的 MySQL 是远远达不到的&#xff0c;所以必须搭建一个主从复制架构&#xff0c;同时可以基于一些工具实现高可用架构&#xff0c;在此基础上&#xff0c…

富富集网络图绘制教程

本期教程 前言 今天学习aPEAR包&#xff0c;绘制KEGG和GO功能富集网络图&#xff0c;用起来还是比较方便的&#xff0c;直接将clusterProfiler富集结果进行绘制&#xff0c;对人类、动物等分析结果非常方便。对于模式植物&#xff0c;使用自己制作的GO或KEGG背景文件进行富集分…

Modbus平台:协议中间件(支持Modbus TCP、RTU、ASCII)

该程序可放置外网中&#xff0c;适用于DTU长连接&#xff08;心跳包必须包含DTU&#xff0c;可以是tcp/udp&#xff09;&#xff0c;也可以在内网中&#xff0c;短连接访问设备server 支持协议&#xff1a;Modbus TCP | RTU | ASCII 连接方式&#xff1a;TcpAtive: TCP主动 | …

嵌入式常见协议---IIC协议

1.IIC&#xff08;IC&#xff09;协议是什么&#xff1f; 全称 Inter-Integrated Circuit ,字面意思是集成电路之间&#xff0c;是IC BUS简称&#xff0c;中文应该叫集成电路总线&#xff0c;是一种串行通信总线&#xff08;同步串行半双工&#xff09;&#xff0c;使用多主从…

给csgo游戏搬砖新手的十大建议

1、不要参与赌博性质的开箱和炼金&#xff0c;因为真的会上瘾&#xff0c;赚了还好&#xff0c;亏了你得哭。 2、实在想要玩饰品&#xff0c;直接去悠悠有品或者网易buff看价格&#xff0c;底价再砍10元&#xff0c;总会有人愿意卖的。 3、在steam上不要接受陌生人的好友申请…