借助juc里的ReentrantLock实现一个阻塞队列结构:


package demo.concurrent.lock.queue; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; /**
* @author sunqinwen
* @version \: SimpleQueue.java,v 0.1 2019-01-16 14:47
* 利用重入锁和重入锁的线程调度实现的简单阻塞队列
*/
public class SimpleQueue { private static ReentrantLock lock = new ReentrantLock(); private T[] nodes; private int tail = 0; // 入元素下标 private int count = 0; // 元素个数 private int head = 0; // 出元素下标 public SimpleQueue(int size) {
nodes = (T[]) new Object[size];
} private static Condition notFull = lock.newCondition(); private static Condition notEmpty = lock.newCondition(); public void put(T t) {
try {
lock.lock();
if (count == nodes.length) { // 队列已满,阻塞
System.out.println("目前队列已满,等待取值中");
notFull.await();
}
if (tail > (nodes.length - 1)) { // 当前游标值已经大于数组游标最大值了,则从0开始计算
tail = 0;
}
nodes[tail] = t; // 给当前游标位赋值
count++; // 入元素元素个数+1
tail++; // 游标值+1
notEmpty.signalAll(); // 走到这里说明队列内至少有一个元素,则唤醒取值
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public T take() {
T t = null;
try {
lock.lock();
if (count == 0) { // 队列已空,等待加值
System.out.println("目前队列已空,等待入值中");
notEmpty.await();
}
if (head > (nodes.length - 1)) { // 若取值游标大于游标最大值,则从0开始计算
head = 0;
}
t = nodes[head]; // 拿到元素值
nodes[head] = null; // 清空原有位置上的值
head++; // 取值游标+1
count--; // 元素个数-1
notFull.signalAll(); // 走到这里说明队列至少有一个空位,则唤醒入值
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
} return t;
} }

以上为主要代码,下面进行简单的测试:


@Test
public void simpleQueueTest() throws Exception { executorService.execute(() -> {
simpleQueue.put(1);
simpleQueue.put(2);
simpleQueue.put(3);
simpleQueue.put(4);
simpleQueue.put(5);
simpleQueue.put(6); simpleQueue.put(7);
simpleQueue.put(8);
simpleQueue.put(9);
simpleQueue.put(10);
simpleQueue.put(11);
simpleQueue.put(12);
}); Thread.sleep(5000L); executorService.execute(() -> { Integer r;
while ((r = simpleQueue.take()) != null) {
System.out.println(r);
}
}); Thread.sleep(5000L);
}

运行结果:


目前队列已满,等待取值中
目前队列已满,等待取值中
1
2
目前队列已满,等待取值中
3
目前队列已满,等待取值中
4
5
6
7
8
9
目前队列已空,等待入值中
10
11
12
目前队列已空,等待入值中

利用ReentrantLock简单实现一个阻塞队列的更多相关文章

  1. 进阶高阶IoT架构-教你如何简单实现一个消息队列

    前言 消息队列是软件系统领域用来实现系统间通信最广泛的中间件.基于消息队列的方式是指由应用中的某个系统负责发送消息,由关心这条消息的相关系统负责接收消息,并在收到消息后进行各自系统内的业务处理.消息可 ...

  2. 用Java如何设计一个阻塞队列,然后说说ArrayBlockingQueue和LinkedBlockingQueue

    前言 用Java如何设计一个阻塞队列,这个问题是在面滴滴的时候被问到的.当时确实没回答好,只是说了用个List,然后消费者再用个死循环一直去监控list的是否有值,有值的话就处理List里面的内容.回 ...

  3. 使用 ReentrantLock 和 Condition 实现一个阻塞队列

    前言 从之前的阻塞队列的源码分析中,我们知道,JDK 中的阻塞队列是使用 ReentrantLock 和 Condition 实现了,我们今天来个简易版的.代码如下: 代码 public class ...

  4. 16_Queue_利用wait()和notify()编写一个阻塞队列

    [线程间通信概念] 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体必用方式之一.当线程存在通信指挥,线程间的交互性会更强大,在提高CPU利用率的同 ...

  5. 浅谈Java中的Condition条件队列,手摸手带你实现一个阻塞队列!

    条件队列是什么?可能很多人和我一样答不出来,不过今天终于搞清楚了! 什么是条件队列 条件队列:当某个线程调用了wait方法,或者通过Condition对象调用了await相关方法,线程就会进入阻塞状态 ...

  6. 利用jdbc简单封装一个小框架(类似DBUtils)

    利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...

  7. 利用Bootstrap简单实现一个文件上传进度条

    © 版权声明:本文为博主原创文章,转载请注明出处 说明: 1. 使用commons-fileupload.jar实现文件上传及进度监听 2. 使用bootstrap的进度条进行页面显示 3. 因为进度 ...

  8. 阻塞队列 - java基于链表的简单实现

    1.阻塞队列的原理 阻塞队列与普通队列的区别在于:阻塞队列为空时,从队列中获取元素的操作将会被阻塞,当队列为满时,往队列里添加元素的操作会被阻塞. 试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其 ...

  9. 用阻塞队列实现一个生产者消费者模型?synchronized和lock有什么区别?

    多线程当中的阻塞队列 主要实现类有 ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序 LinkedBlockingQueue是一个基于链表结构的 ...

随机推荐

  1. Laravel 引入自定义类库或第三方类库

    强烈建议引入的类 都是含有命名空间的,这样使用起来就不会出现重名的情况.!!当然,没有命名空间也可以使用,就是类名字(非文件名)最好复杂一些.(重复也不要紧,程序会自己判断) laravel5.4中如 ...

  2. VMWare 虚拟机挂载 Homestead NFS 进行老项目(基于 Brophp)维护

    环境: Laravel/homestead + winnfsd VMWare workstation 背景: 众所周知, windows 上成功配置 Homestead 进行开发时,为了解决文件系统的 ...

  3. Spring JMX之二:远程访问MBean

    虽然最初的JMX规范提及了通过MBean进行应用的远程管理,但是它并没有定义实际的远程 访问协议或API.因此,会由JMX供应商定义自己的JMX远程访问解决方案,但这通常又是专 有的. 为了满足以标准 ...

  4. mysql索引原理及用法

    MySQL索引原理及慢查询优化 Mysql explain用法和性能分析 MySQL 索引优化全攻略 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术,能够大大提 ...

  5. Android应用程序的基本组件介绍

    1.Activity和View Activity是Android应用中负责与用户交互的组件,它只能通过setContentView(View)来显示指定组件. View组件是所有UI控件.容器空间的基 ...

  6. Caffe 议事(三):从零开始搭建 ResNet 之 网络的搭建(中)

    上面2个函数定义好了,那么剩下的编写网络就比较容易了,我们在ResNet结构介绍中有一个表,再贴出来: Layer_name Output_size 20-layer ResNet Conv1 32 ...

  7. Java开发环境之------MyEclipse快捷键和排除错误第一选择ctrl+1(***重点***:ctrl+1,快速修复---有点像vs中的快速using

    using Java开发环境之------MyEclipse快捷键和排除错误第一选择ctrl+1(***重点***:ctrl+1,快速修复---有点像vs中的快速using 2015-06-29 浏览 ...

  8. 数据挖掘算法以及其实现zz

    实验一    分类技术及其应用 实习要求: 基于线性回归模型拟合一个班学生的学习成绩,建立预测模型.数据可由自己建立100个学生的学习成绩. 1)    算法思想: 最小二乘法 设经验方程是y=F(x ...

  9. SGU 194 Reactor Cooling (有容量和下界的可行流)

    题意:给定上一个有容量和下界的网络,让你求出一组可行解. 析:先建立一个超级源点 s 和汇点 t ,然后在输入时记录到每个结点的下界的和,建边的时候就建立c - b的最后再建立 s 和 t , 在建立 ...

  10. Objective-C 学习笔记(四) 数组

    Objective-C 数组作为函数参数传递 如果想在一个函数作为参数,通过一维数组,就必须声明函数形式参数 方式一    指针作为形式参数 - (void) myFunction(int *) pa ...