通过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构造有界缓存队列与数据栈相关推荐

  1. java 多线程缓存_[Java教程]【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列...

    [Java教程][JAVA并发编程实战]12.使用condition实现多线程下的有界缓存先进先出队列 0 2016-11-29 17:00:10 package cn.study.concurren ...

  2. 有界阻塞队列ArrayBlockingQueue和无界阻塞队列LinkedBlockingQueue

    ArrayBlockingQueue和LinkedBlockingQueue最大的区别是一个是有界无界,各有优劣. 先看实例代码: main函数起2个线程模拟生成消费者 import java.uti ...

  3. Java 多线程 —— ReentrantLock 与 Condition

    引言 ReentrantLock 是 JUC 下的一个功能强劲的锁工具,支持公平锁.非公平锁,以及多等待队列的 Condition . 也常常被称为"手动锁".本篇博客主要分析它的 ...

  4. 类 ArrayBlockingQueueE(一个由数组支持的有界阻塞队列。)

    类型参数: E - 在此 collection 中保持的元素类型 所有已实现的接口: Serializable, Iterable<E>, Collection<E>, Blo ...

  5. Java多线程(九)之ReentrantLock与Condition

    一.ReentrantLock 类 1.1 什么是reentrantlock java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java ...

  6. JDK1.8源码分析:可重入锁ReentrantLock和Condition的实现原理

    synchronized的用法和实现原理 synchronized实现线程同步的用法和实现原理 不足 synchronized在线程同步的使用方面,优点是使用简单,可以自动加锁和解锁,但是也存在一些不 ...

  7. ReentrantLock中Condition的使用

    一.Condition的作用 ReentrantLock虽然实现了互斥,但是如何实现进程间的相互通信呢? 这就需要借助Condition来实现. 就像synchronized实现互斥,同时配合noti ...

  8. ReentrantLock和Condition理解及应用

    Condition: Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal 或者 signalAll方法被带 ...

  9. Lock锁中ReentrantLock中Condition的使用

    package com.lezu.springboot.controller;import java.util.concurrent.locks.Condition; import java.util ...

  10. ReentrantLock的Condition条件实现精确唤醒某个线程

    /*** 描述: 介绍Reentrantlock的condition条件可以实现精确唤醒某个线程* 题目:多线程之间按顺序调用,实现A->B->C三个线程启动,要求AA打印5次BB打印10 ...

最新文章

  1. 【Android SOAP】基于第三方开源项目ksoap-android
  2. 如何正确选择开源数据库?你需要这的5个技巧
  3. 微软正式推免费Word 电脑商Office收费降60%
  4. 入行Python需要看的4本书推荐
  5. 免费下载 | 超级APP背后的移动端技术大揭秘
  6. java nio2 iocp_基于JDK7 NIO2的高性能web服务器实践之二(转)
  7. macbook图形化编程_如何判断MacBook使用的是哪种图形芯片(并进行切换)
  8. 【转】接口 与 抽象类
  9. php mysql 地图 矩形_PHP+Mysql+jQuery中国地图区域数据统计实例讲解
  10. linux元组和列表的区别,列表,元组,集合
  11. JS判断对象是不是数组“Array”
  12. [COGS2639]偏序++
  13. python统计word页码_使用Python(win32com)在MS Word表中插入带页码的字段
  14. 拍照尺寸 ios_即将收费!11款价值80元iOS限免应用,全部免费下载
  15. 【Linux运维】01-Linux运维概述与CentOS系统安装
  16. 发送文件夹不存在或被删除
  17. ogg for bigdata hbase安装步骤
  18. HI618E音频解码芯片
  19. Rewritecond介绍
  20. 通过Java实现求水仙花数

热门文章

  1. Lambda表达式公共拼接函数(原创)
  2. 解决jenkins插件列表为空的问题
  3. 探讨下在Delphi里面进程之间的数据共享
  4. [No0000F5]C# 类(Class)
  5. 工作中一些环境问题解决记录
  6. Search in Rotated Sorted Array II leetcode java
  7. 马云:大部分失败企业都是因为不够专注
  8. ORACLE 常用函数——字符函数
  9. BUG报告:habahaba风格,图片显示有问题
  10. 同步、异步、堵塞、非堵塞概念总结