当前位置: 首页 > news >正文

【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是伴随的,同时执行顺序非固定,说明阻塞队列里边其实不存元素。

http://www.lryc.cn/news/30951.html

相关文章:

  • Fragment中获取Activity的一点点建议
  • Java Math类
  • Javascript -- 加载时间线 正则表达式
  • gdb/git的基本使用
  • 信息安全与数学基础-笔记-④二次同余方程
  • Luogu P4447 [AHOI2018初中组]分组
  • 手把手创建flask项目
  • SpringCloud-4_Eureka服务注册与发现
  • 【react全家桶】生命周期
  • 虚拟机安装Windows 10
  • 【CMU15-445数据库】bustub Project #2:B+ Tree(下)
  • leetcode 困难 —— 外星文字典(拓扑排序)
  • ubuntu server 18.04使用tensorflow进行ddqn训练全过程
  • 2023年全国最新二级建造师精选真题及答案14
  • mysql一条语句的写入原理
  • 嵌入式Linux内核代码风格(二)
  • Spring Boot @Aspect 切面编程实现访问请求日志记录
  • 初学者的第一个Linux驱动
  • 7. 拼数
  • Java每天15道面试题 | Redis
  • 13_pinctrl子系统
  • Linux系统对于实施人员的价值
  • ForkJoin 和 Stream并行流
  • 逻辑优化-cofactor
  • 车道线检测CondLaneNet论文和源码解读
  • vue3的插槽slots
  • docker学校服务器管理
  • pv和pvc
  • k8s篇之Pod 干预与 PDB
  • Django学习17 -- ManytoManyField