【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],将它们联接成一排,相邻数字首尾相接,组成一个最大的整…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
