使用 ReentrantLock 和 Condition 实现一个阻塞队列
前言
从之前的阻塞队列的源码分析中,我们知道,JDK 中的阻塞队列是使用 ReentrantLock 和 Condition 实现了,我们今天来个简易版的。代码如下:
代码
public class BoundedBuffer {
final ReentrantLock lock = new ReentrantLock();
final ConditionObject notFull = (ConditionObject) lock.newCondition();
final ConditionObject notEmpty = (ConditionObject) lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
// 当数组满了
while (count == items.length) {
// 释放锁,等待
notFull.await();
}
// 放入数据
items[putptr] = x;
// 如果到最后一个位置了,下标从头开始,防止下标越界
if (++putptr == items.length) {
// 从头开始
putptr = 0;
}
// 对 count ++ 加加
++count;
// 通知 take 线程,可以取数据了,不必继续阻塞
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
// 如果数组没有数据,则等待
while (count == 0) {
notEmpty.await();
}
// 取数据
Object x = items[takeptr];
// 如果到数组尽头了,就从头开始
if (++takeptr == items.length) {
// 从头开始
takeptr = 0;
}
// 将数量减1
--count;
// 通知阻塞的 put 线程可以装填数据了
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
其实,这并不是我写的,而是 Condition 接口的 JavaDoc 文档中写的。并且文档中说,请不要再次实现这个队列,因为 JDK 内部已经是实现了。原话如下:
(The {@link java.util.concurrent.ArrayBlockingQueue} class provides this functionality, so there is no reason to implement this sample usage class.)
楼主只是觉得这个代码写的挺好的,所以分享一下,其中关键的还是 Condition 和重入锁,重入锁的核心源码我们已经看过了,今天来看看 Condition 的源码。所以我们今天使用了这个代码作为一个入口。
可以看到,Condition 的重要方法就是 await 和 signal,类似 Object 类的 wait 和 notify 方法。
我们后面会详细讲讲这两个方法的实现。
使用 ReentrantLock 和 Condition 实现一个阻塞队列的更多相关文章
- 利用ReentrantLock简单实现一个阻塞队列
借助juc里的ReentrantLock实现一个阻塞队列结构: package demo.concurrent.lock.queue; import java.util.concurrent.lock ...
- 用Java如何设计一个阻塞队列,然后说说ArrayBlockingQueue和LinkedBlockingQueue
前言 用Java如何设计一个阻塞队列,这个问题是在面滴滴的时候被问到的.当时确实没回答好,只是说了用个List,然后消费者再用个死循环一直去监控list的是否有值,有值的话就处理List里面的内容.回 ...
- 浅谈Java中的Condition条件队列,手摸手带你实现一个阻塞队列!
条件队列是什么?可能很多人和我一样答不出来,不过今天终于搞清楚了! 什么是条件队列 条件队列:当某个线程调用了wait方法,或者通过Condition对象调用了await相关方法,线程就会进入阻塞状态 ...
- 使用lock和condition实现的阻塞队列-字符串
在jdk 的API中提供了一个字符串的阻塞队列 : class BoundedBuffer { final Lock lock = new ReentrantLock(); final Conditi ...
- ReentrantLock与Condition构造有界缓存队列与数据栈
通过ReentrantLock与Condition的设计,以数组为基础,可以实现简单的队列和栈的数据结构,临界阻塞的效果. ReentrantLock相对于synchronized比较大的一个区别是有 ...
- 16_Queue_利用wait()和notify()编写一个阻塞队列
[线程间通信概念] 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体必用方式之一.当线程存在通信指挥,线程间的交互性会更强大,在提高CPU利用率的同 ...
- 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题
调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...
- 用阻塞队列实现一个生产者消费者模型?synchronized和lock有什么区别?
多线程当中的阻塞队列 主要实现类有 ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序 LinkedBlockingQueue是一个基于链表结构的 ...
- 聊聊高并发(十四)理解Java中的管程,条件队列,Condition以及实现一个堵塞队列
这篇里面有一些主要的概念,理解概念是件有意义的事情,仅仅有理解概念才干在面对详细问题的时候找到正确的解决思路.先看一下管程的概念 第一次在书上看到管程这个中文名称认为非常迷糊,管程究竟是个什么东东,于 ...
随机推荐
- RxSwift学习笔记2:Observable/生命周期/Event/oneNext/onError/onCompleted/
Observable 是 Rx 的根基 官网:http://reactivex.io/ github地址:https://github.com/ReactiveX/RxSwift Observabl ...
- Screen、IP
主要内容 Screen 安装screen [root@TS-DEV ~]# yum install screen [root@TS-DEV ~]# rpm -qa|grep screen screen ...
- 多条件情况查询,sql select case when when else
多条件情况查询 SELECT Title, 'Price Range' = CASE WHEN price IS NULL THEN 'Unpriced' ...
- 利用C#迭代器的一个杨辉三角示例
身边有个朋友在跟着廖雪峰的教程学习python,途中遇到了"在Python中使用迭代器打印杨辉三角"的问题,我在帮忙解决的同时顺手写了个简单的C#版本以供补充. internal ...
- ASP.NET MVC WebAPI实现文件批量上传
工作中学习,学习中记录~~~~~~ 最下面附上demo 任务需求:需要做一个apI接口让C#的程序调用实现批量文件的上传. 难度: 没有做过通过API上传文件的...之前做过网站前后台上传. 首先当然 ...
- 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresenter, ListViewItemPresenter
[源码下载] 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresen ...
- Swift5 语言指南(二十一) 嵌套类型
通常创建枚举以支持特定类或结构的功能.类似地,定义纯粹在更复杂类型的上下文中使用的实用程序类和结构可能是方便的.为此,Swift允许您定义嵌套类型,从而在它们支持的类型定义中嵌套支持枚举,类和结构. ...
- Windows打开应用,提示“此程序被组策略阻止”
Windows打开应用,提示"此程序被组策略阻止",该问题为组策略限制了用户使用某个应用程序,一般可以在 1 控制面板--->管理工具--->本地安全策略-->软 ...
- mybatis四大接口之 ParameterHandler
1. 继承结构 只有一个默认的实现类 2. ParameterHandler 获取参数对象: 设置参数对象: public interface ParameterHandler { Object g ...
- POJ 2470
#include<iostream> #include<stdio.h> #include<vector> using namespace std; int mai ...