【Java开发】JUC进阶 03:读写锁、阻塞队列、同步队列
1 读写锁(ReadWriteLock)
📌 要点
实现类:ReentrantReadWirteLock
通过读写锁实现更细粒度的控制,当然通过Synchronized和Lock锁也能达到目的,不过他们会在写入和读取操作都给加锁,影响性能;
读写锁在加锁同时,给读取操作进行优化,简单来说性能更高;
读写锁中,读锁是共享锁,多个线程可以同时占有;写锁是独占锁,一次只能被一个线程占有。
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockDemo {public static void main(String[] args) {MyCache myCache = new MyCache();//写入for (int i = 0; i < 5; i++) {final int temp = i;new Thread(()->{myCache.put(temp+"",temp+"");},String.valueOf(i)).start();}//读取for (int i = 0; i < 5; i++) {final int temp = i;new Thread(()->{myCache.get(temp+"");},String.valueOf(i)).start();}}
}//自定义缓存
class MyCache{private volatile Map<String,Object> map = new HashMap<>();//读写锁,更细粒度的控制private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();//存、写入的时候,只希望同时只有一个线程写public void put(String key,Object value){readWriteLock.writeLock().lock();try {System.out.println(Thread.currentThread().getName()+"写入"+key);map.put(key,value);System.out.println(Thread.currentThread().getName()+"写入OK");} catch (Exception e) {e.printStackTrace();} finally {readWriteLock.writeLock().unlock();}}//取、读,所有人都可以读public void get(String key){readWriteLock.readLock().lock();try {System.out.println(Thread.currentThread().getName()+"读取"+key);map.get(key);System.out.println(Thread.currentThread().getName()+"读取OK");} catch (Exception e) {e.printStackTrace();} finally {readWriteLock.readLock().unlock();}}
}控制台输出:

2 阻塞队列(BlockingQueue)
阻塞队列(BlockingQueue) 是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
📌 常用实现类

📌 UML相关图

📌 四组API
方式 | 抛出异常 | 不会抛异常,有返回值 | 阻塞等待 | 超时等待 |
添加操作 | add() | offer()供应 | put() | offer(E e, long timeout,TimeUnit unit) |
移除操作 | remove() | poll()获得 | take() | poll(long timeout, TimeUnit unit) |
判断队列首部 | element() | peek()偷看,偷窥 |
📌 代码举例
public class BlockingQueueDemo {public static void main(String[] args) throws InterruptedException {//队列的大小ArrayBlockingQueue queue = new ArrayBlockingQueue(3);System.out.println(queue.offer("A"));System.out.println(queue.offer("B"));System.out.println(queue.offer("C"));System.out.println(queue.offer("D",2, TimeUnit.SECONDS));System.out.println("------------------------");System.out.println(queue.poll());System.out.println(queue.poll());System.out.println(queue.poll());System.out.println(queue.poll());}控制台输出:

3 同步队列(SynchronousQueue)
简单来说,SynchronousQueue是一个没有数据缓冲的阻塞队列,它是实现AbstractQueue接口的。
SynchronousQueue容量为0,生产者线程插入数据(put)必须等待消费者的移除数据(take),反之亦然,也就是说同步队列的插入和移除必须是同步的。
public class SynchronousQueueDemo {public static void main(String[] args) throws InterruptedException {SynchronousQueue<String> queue = new SynchronousQueue<>();//同步队列new Thread(()->{for (int i = 1; i <= 3; i++) {try {queue.put(String.valueOf(i));System.out.println(Thread.currentThread().getName()+"put "+i);} catch (InterruptedException e) {e.printStackTrace();}}}).start();new Thread(()->{for (int i = 1; i <= 3; i++) {try {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName()+"take "+queue.take());} catch (InterruptedException e) {e.printStackTrace();}}}).start();}
}控制台输出:

📢 可以看到put和take是伴随的,同时执行顺序非固定,说明阻塞队列里边其实不存元素。
相关文章:
【Java开发】JUC进阶 03:读写锁、阻塞队列、同步队列
1 读写锁(ReadWriteLock)📌 要点实现类:ReentrantReadWirteLock通过读写锁实现更细粒度的控制,当然通过Synchronized和Lock锁也能达到目的,不过他们会在写入和读取操作都给加锁,影响性能&#x…...
Fragment中获取Activity的一点点建议
平时的Android开发中,我们经常要在Fragment中去获取当前的Activity实例,刚开始的时候可能使用使用Fragment提供的getActivity方法来获取,但是这个方法可能返回null,为了让程序可以正常运行,项目中就出现大量下面这样的…...
Java Math类
Java Math 类是 Java 标准库中提供的一个数学计算类,它提供了很多数学函数,如三角函数、指数函数、对数函数等。在实际工作中,Java Math 类常常被用于处理数学计算问题,例如计算复杂的数学公式、实现数学算法等。本文将详细介绍 J…...
Javascript -- 加载时间线 正则表达式
js加载时间线 1、创建Document对象,开始解析web页面,解析html元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段的document.readyState ‘loading’ 2、遇到link外部css,创建线程加载,并继续解析文档 3、遇到…...
gdb/git的基本使用
热爱编程的你,一定经常徘徊在写bug和改bug之间,调试器也一定是你随影而行的伙伴,离开了它你应该会寝食难安吧! 目录 gdb的使用 断点操作 运行调试 观察数据 Git的使用 仓库的创建和拉取 .gitignore “三板斧” 常用指令 gd…...
信息安全与数学基础-笔记-④二次同余方程
知识目录二次同余方程的解欧拉判别式Legendre (勒让德符号)二次同余方程的解 什么是二次同余方程的解 注意这里二次同余方程和一次同余方程是不一样的 在x2x^2x2 三 a (mod m) 方程中举例 ↓ 解即剩余类,因为是模m,所以我们在 [ 0, m-1 ]中逐个代入看是…...
Luogu P4447 [AHOI2018初中组]分组
题目链接:传送门 将nnn个可重复的整数分为mmm组,每组中的数必须连续且不重复,使人数最少的组人数最多。 两个最值肯定第一想到二分,每次二分出一个值,判断在这个值为答案的前提下能否完成分组。 在思考判别函数时发现…...
手把手创建flask项目
Flask 框架流程 什么是Flask: Flask诞生于2010年, 使用python语言基于Werkzeug工具箱编写的轻量级Web开发框架 Flask本身相当于一个内核, 其他几乎所有的功能都要用到扩展(邮件:Flask-Mail, 用户认证:Flask-Login, 数据库:Flask-SQLAlchemy). Flask的核心在于Werkz…...
SpringCloud-4_Eureka服务注册与发现
Eureka作为一个老牌经典的服务注册&发现技术,其设计和理念,也在影响后面的组件。目前主流的服务注册&发现的组件是Nacos当前项目架构问题分析-引出Eureka问题分析:1.在企业级项目中,服务消费访问请求会存在高并发2.如果只…...
【react全家桶】生命周期
文章目录04 【生命周期】1.简介2.初始化阶段2.1 constructor2.2 componentWillMount(即将废弃)2.3 static getDerivedStateFromProps(新钩子)2.4 render2.5 componentDidMount2.6 初始化阶段总结3.更新阶段3.1 componentWillRecei…...
虚拟机安装Windows 10
虚拟机安装Windows 10 镜像下载 方法一:下载我制作好的镜像文件->百度网盘链接 提取码:Chen 方法二:自己做一个 进入微软官网链接 下载"MediaCreationTool20H2" 运行该工具 点击下一步选择路径,等他下载好就欧克了…...
【CMU15-445数据库】bustub Project #2:B+ Tree(下)
Project 2 最后一篇,讲解 B 树并发控制的实现。说实话一开始博主以为这块内容不会很难(毕竟有 Project 1 一把大锁摆烂秒过的历史x),但实现起来才发现不用一把大锁真的极其痛苦,折腾了一周多才弄完。 本文分基础版算法…...
leetcode 困难 —— 外星文字典(拓扑排序)
题目: 现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。 给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。 请你根据该词典还原出此语言中已知的字…...
ubuntu server 18.04使用tensorflow进行ddqn训练全过程
0. 前言 需要使用ddqn完成某项任务,为了快速训练,使用带有GPU的服务器进行训练。记录下整个过程,以及遇到的坑。 1. 选择模板代码 参考代码来源 GitHub 该代码最后一次更新是Mar 24, 2020。 环境配置: python3.8 运行安装脚本…...
2023年全国最新二级建造师精选真题及答案14
百分百题库提供二级建造师考试试题、二建考试预测题、二级建造师考试真题、二建证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 二、多选题 61.已经取得下列资质的设计单位,可以直接申请相应类别施工总承包一级…...
mysql一条语句的写入原理
mysql写入原理 我们知道在mysql数据库最核心的大脑就是执行引擎; 其中的默认引擎Innodb在可靠执行和性能中做出来平衡; innodb支持在事务控制、读写效率,多用户并发,索引搜索方面都表现不俗; innodb如何进行数据写入…...
嵌入式Linux内核代码风格(二)
第九章:你已经把事情弄糟了 这没什么,我们都是这样。可能你的使用了很长时间Unix的朋友已经告诉你“GNU emacs”能 自动帮你格式化C源代码,而且你也注意到了,确实是这样,不过它所使用的默认值和我们 想要的相去甚远&a…...
Spring Boot @Aspect 切面编程实现访问请求日志记录
aop切面编程想必大家都不陌生了,aspect可以很方便开发人员对请求指定拦截层,一般是根据条件切入到controller控制层,做一些鉴权、分析注解、获取类名方法名参数、记录操作日志等。 在SpringBoot中使用aop首先是要导入依赖如下: …...
初学者的第一个Linux驱动
软件环境:Ubuntu20.04 Linux内核源码:3.4.39 硬件环境:GEC6818 什么是驱动?简单来说就是让硬件工作起来的程序代码。 Linux驱动模块加载有两种方式: 1、把写好的驱动代码直接编译进内核。 2、把写好的驱动代码编…...
7. 拼数
1 题目描述 拼数成绩10开启时间2021年09月24日 星期五 18:00折扣0.8折扣时间2021年11月15日 星期一 00:00允许迟交否关闭时间2021年11月23日 星期二 00:00 设有 n个正整数 a[1]…a[n],将它们联接成一排,相邻数字首尾相接,组成一个最大的整…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
