ReentrantLock与Condition构造有界缓存队列与数据栈
通过ReentrantLock与Condition的设计,以数组为基础,可以实现简单的队列和栈的数据结构,临界阻塞的效果。
ReentrantLock相对于synchronized比较大的一个区别是有条件变量:Condition,很大一个程度上是为了解决Object.wait/notify/notifyAll难以使用的问题。Condition(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait
做的那样。多个Condition需要绑定到同一锁上,可以实现队列与栈。
队列:先进先出的原则
栈:先进后出的原则
类一:模拟队列的读写操作
1 package reentranlock; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class BoundedBufferQueue { 8 9 static Lock lock = new ReentrantLock(); 10 static Condition read = lock.newCondition(); 11 static Condition write = lock.newCondition(); 12 static Object [] data = new Object [10];// 构造一个缓存队列 13 14 private static int count = 0;// 用来标识队列中存放的数据量 15 private static int readIndex = 0;// 标识读取的下标 16 private static int writeIndex = 0;// 标识写入的下标 17 18 public static void put(Integer num) throws InterruptedException { 19 try { 20 lock.lock(); 21 if (count == 10) { 22 write.await();// 数据量满了则阻塞写的操作 23 } 24 data[writeIndex] = num; 25 count++; 26 if (++writeIndex == 10) {// 循环写入数据 27 writeIndex = 0; 28 } 29 read.signal();// 触发读操作 30 } finally { 31 lock.unlock(); 32 } 33 } 34 35 public static Object take() throws InterruptedException { 36 Object result = null; 37 try { 38 lock.lock(); 39 if (count == 0) {// 如果队列无数据量则阻塞读操作 40 read.await(); 41 } 42 result = (Integer) data[readIndex]; 43 count--; 44 if (++readIndex == 10) {// 循环取数据 45 readIndex = 0; 46 } 47 write.signal();// 触发写操作 48 } finally { 49 lock.unlock(); 50 } 51 return result; 52 } 53 54 // 下面是模拟读写操作过程,可以通过操作时间不同来验证队列读取。 55 public static void main(String[] args) throws InterruptedException { 56 57 Runnable readThread = new Runnable() { 58 @Override 59 public void run() { 60 while(true){ 61 for(int i=1;i<Integer.MAX_VALUE;i++){ 62 try { 63 Integer o = (Integer) take(); 64 System.out.println("读取:"+o); 65 Thread.sleep(3000); 66 } catch (InterruptedException e) { 67 e.printStackTrace(); 68 } 69 } 70 } 71 72 } 73 }; 74 75 Runnable writeThread = new Runnable() { 76 @Override 77 public void run() { 78 while(true){ 79 for(int i=1;i<Integer.MAX_VALUE;i++){ 80 try { 81 put(i); 82 System.out.println("写入:"+i); 83 Thread.sleep(1000); 84 } catch (InterruptedException e) { 85 e.printStackTrace(); 86 } 87 } 88 } 89 90 } 91 }; 92 93 Thread read = new Thread(readThread); 94 Thread write = new Thread(writeThread); 95 96 read.start(); 97 Thread.currentThread().join(1000); 98 write.start(); 99 } 100 101 }
类二:模拟栈的读写操作
1 package reentranlock; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class BoundedBufferStack { 8 9 static Lock lock = new ReentrantLock(); 10 static Condition read = lock.newCondition(); 11 static Condition write = lock.newCondition(); 12 static Object [] data = new Object [10];// 构造一个缓存栈 13 14 private static int count = 0;// 用来标识栈中存放的数据量 15 private static int index = 0;// 标识的下标 16 17 public static void put(Integer num) throws InterruptedException { 18 try { 19 lock.lock(); 20 if (count == 10) {// 数据量满了则阻塞写操作 21 write.await(); 22 } 23 data[index] = num; 24 count++; 25 index++; 26 if (index == 10) { 27 index = 0; 28 } 29 read.signal();// 触发读操作 30 } finally { 31 lock.unlock(); 32 } 33 } 34 35 public static Object take() throws InterruptedException { 36 Object result = null; 37 try { 38 lock.lock(); 39 if (count == 0) {// 数据量为空则阻塞读操作 40 read.await(); 41 } 42 if(index == 0 && count == 10){// 为了仿造栈的后进先出的模式,取最后写入的数据 43 index = 9; 44 }else{ 45 index --; 46 } 47 result = (Integer) data[index]; 48 count--; 49 if (index == 0) { 50 index = 0; 51 } 52 write.signal();// 触发写操作 53 } finally { 54 lock.unlock(); 55 } 56 return result; 57 } 58 59 // 下面是模拟读写操作过程,可以通过操作时间不同来验证栈的读取。 60 public static void main(String[] args) throws InterruptedException { 61 62 Runnable readThread = new Runnable() { 63 @Override 64 public void run() { 65 while(true){ 66 for(int i=1;i<Integer.MAX_VALUE;i++){ 67 try { 68 Integer o = (Integer) take(); 69 System.out.println("读取:"+o); 70 Thread.sleep(5000); 71 } catch (InterruptedException e) { 72 e.printStackTrace(); 73 } 74 } 75 } 76 77 } 78 }; 79 80 Runnable writeThread = new Runnable() { 81 @Override 82 public void run() { 83 while(true){ 84 for(int i=1;i<Integer.MAX_VALUE;i++){ 85 try { 86 put(i); 87 System.out.println("写入:"+i); 88 Thread.sleep(1000); 89 } catch (InterruptedException e) { 90 e.printStackTrace(); 91 } 92 } 93 } 94 95 } 96 }; 97 98 Thread read = new Thread(readThread); 99 Thread write = new Thread(writeThread); 100 101 write.start(); 102 Thread.currentThread().join(1000); 103 read.start(); 104 } 105 106 }
ArrayBlockingQueue也是这种设计 "通过平衡生产者和消费者的处理能力来提高整体处理数据的速度",只不过运用ArrayBlockingQueue不要担心非单一生产者/消费者场景下的系统假死问题,缓冲区空、缓冲区满的场景BlockingQueue都是定义了不同的Condition,所以不会唤醒自己的同类。
转载于:https://www.cnblogs.com/hupu-jr/p/7762477.html
ReentrantLock与Condition构造有界缓存队列与数据栈相关推荐
- java 多线程缓存_[Java教程]【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列...
[Java教程][JAVA并发编程实战]12.使用condition实现多线程下的有界缓存先进先出队列 0 2016-11-29 17:00:10 package cn.study.concurren ...
- 有界阻塞队列ArrayBlockingQueue和无界阻塞队列LinkedBlockingQueue
ArrayBlockingQueue和LinkedBlockingQueue最大的区别是一个是有界无界,各有优劣. 先看实例代码: main函数起2个线程模拟生成消费者 import java.uti ...
- Java 多线程 —— ReentrantLock 与 Condition
引言 ReentrantLock 是 JUC 下的一个功能强劲的锁工具,支持公平锁.非公平锁,以及多等待队列的 Condition . 也常常被称为"手动锁".本篇博客主要分析它的 ...
- 类 ArrayBlockingQueueE(一个由数组支持的有界阻塞队列。)
类型参数: E - 在此 collection 中保持的元素类型 所有已实现的接口: Serializable, Iterable<E>, Collection<E>, Blo ...
- Java多线程(九)之ReentrantLock与Condition
一.ReentrantLock 类 1.1 什么是reentrantlock java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java ...
- JDK1.8源码分析:可重入锁ReentrantLock和Condition的实现原理
synchronized的用法和实现原理 synchronized实现线程同步的用法和实现原理 不足 synchronized在线程同步的使用方面,优点是使用简单,可以自动加锁和解锁,但是也存在一些不 ...
- ReentrantLock中Condition的使用
一.Condition的作用 ReentrantLock虽然实现了互斥,但是如何实现进程间的相互通信呢? 这就需要借助Condition来实现. 就像synchronized实现互斥,同时配合noti ...
- ReentrantLock和Condition理解及应用
Condition: Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal 或者 signalAll方法被带 ...
- Lock锁中ReentrantLock中Condition的使用
package com.lezu.springboot.controller;import java.util.concurrent.locks.Condition; import java.util ...
- ReentrantLock的Condition条件实现精确唤醒某个线程
/*** 描述: 介绍Reentrantlock的condition条件可以实现精确唤醒某个线程* 题目:多线程之间按顺序调用,实现A->B->C三个线程启动,要求AA打印5次BB打印10 ...
最新文章
- 【Android SOAP】基于第三方开源项目ksoap-android
- 如何正确选择开源数据库?你需要这的5个技巧
- 微软正式推免费Word 电脑商Office收费降60%
- 入行Python需要看的4本书推荐
- 免费下载 | 超级APP背后的移动端技术大揭秘
- java nio2 iocp_基于JDK7 NIO2的高性能web服务器实践之二(转)
- macbook图形化编程_如何判断MacBook使用的是哪种图形芯片(并进行切换)
- 【转】接口 与 抽象类
- php mysql 地图 矩形_PHP+Mysql+jQuery中国地图区域数据统计实例讲解
- linux元组和列表的区别,列表,元组,集合
- JS判断对象是不是数组“Array”
- [COGS2639]偏序++
- python统计word页码_使用Python(win32com)在MS Word表中插入带页码的字段
- 拍照尺寸 ios_即将收费!11款价值80元iOS限免应用,全部免费下载
- 【Linux运维】01-Linux运维概述与CentOS系统安装
- 发送文件夹不存在或被删除
- ogg for bigdata hbase安装步骤
- HI618E音频解码芯片
- Rewritecond介绍
- 通过Java实现求水仙花数