阻塞队列-单锁实现

news/2024/12/23 13:00:56/

使用阻塞队列  

当我们多个线程下 对 一个队列进行操作,队列满了的情况下,其他线程再次 offer,会一直阻塞等待

对一个队列进行出队操作的时候,队列空的情况下,会一直阻塞等待删除,直到队列有元素的时候,会执行删除操作

一直阻塞等待的时候用自旋锁来进行等待

代码如下

阻塞队列接口

java">public interface BlockingQueue <E>{void offer(E e) throws InterruptedException;Boolean offer(E e,long timeout) throws InterruptedException;E poll() throws InterruptedException;
}

阻塞队列实现

java">
public class ArrayBlockingQueue<E> implements BlockingQueue<E> {private final E[] array;private int head;//记录出队时候的头指针private int tail;//记录入队的指针private int size;//记录数组 个数private ReentrantLock lock = new ReentrantLock();private Condition headWait = lock.newCondition();//控制 入队的 同步队列private Condition tailWait = lock.newCondition();//控制出队的同步队列public ArrayBlockingQueue(int capacity) {array = (E[]) new Object[capacity];}private Boolean isFull() {return size == array.length;}private Boolean isEmpty() {return size == 0;}@Overridepublic String toString() {return "ArrayBlockingQueue{" +"array=" + Arrays.toString(array) +'}';}/*** @param e* @throws InterruptedException 在判断是否满的时候 用while循环而不是 if 为了防止虚假唤醒*/@Overridepublic void offer(E e) throws InterruptedException {lock.lockInterruptibly();try {while (isFull()) {tailWait.await();//如果满了 就让线程加入 同步队列// 一直等待被唤醒 使用while防止 多线程下的虚假唤醒}array[tail] = e;if (++tail == array.length) {tail = 0;}size++;//唤醒 出队的线程是为了 防止  在一个空队列中,删除元素的线程会一直线程等待,我们唤醒该线程//提示他可以删除headWait.signal();} finally {lock.unlock();}}/*** @param e* @param timeout* @return {@code Boolean }* @throws InterruptedException 根据 自己传入的时间   设置 入队最多等待的时间 如果*                              入队超时    那么返回false 并且该线程不会再等待唤醒*                              跟单独使用awaitNanos方法是不一样的*                               单独使用 .awaitNanos 方法  当设置的等待时间到期,线程自动启动来竞争锁*                               ,竞争不到 会到等待队列中去等待被唤醒*/@Overridepublic Boolean offer(E e, long timeout) throws InterruptedException {lock.lockInterruptibly();//把传入的毫秒 转换成纳秒long nanos = TimeUnit.MILLISECONDS.toNanos(timeout);try {while (isFull()) {if (nanos < 0) {//发现等待的时间 <0 表明超过了自己等待的时间 插入操作入队return false;}nanos = tailWait.awaitNanos(nanos);}array[tail] = e;if (++tail == array.length) {tail = 0;}size++;//唤醒 出队的线程是为了 防止  在一个空队列中,删除元素的线程会一直线程等待,我们唤醒该线程//提示他可以删除headWait.signal();return true;} finally {lock.unlock();}}@Overridepublic E poll() throws InterruptedException {lock.lockInterruptibly();try {while (isEmpty()) {headWait.await();}E e = array[head];array[head] = null;if (++head == array.length) {head = 0;}size--;tailWait.signal();//因为 我们 入队 满了的话线程等待// 删除成功之后 队列不满,唤醒入队线程return e;} finally {lock.unlock();}}
}

测试实现

java">public class ArrayBlockingQueueTest {public static void main(String[] args) throws InterruptedException {ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(3);new Thread(new Runnable() {@Overridepublic void run() {try {blockingQueue.offer("任务2");blockingQueue.offer("任务3");blockingQueue.offer("任务4");System.out.println(blockingQueue.offer("任务1", 1000));} catch (InterruptedException e) {throw new RuntimeException(e);}}},"线程1").start();
Thread.sleep(2000);System.out.println(blockingQueue.toString());}

注意事项

我们只需要注意 condition的awaitnanos 方法,我们等待的时间一到,该线程自动唤醒争抢锁


http://www.ppmy.cn/news/1520368.html

相关文章

Shell编程--sed

介绍--逐行处理模式 非交互式的编辑器&#xff0c;处理时&#xff0c;会把文本先存储在临时缓冲区&#xff0c;叫模式空间&#xff0c;文件不会改变&#xff0c;只会显示在屏幕上&#xff0c;周到使用重定向输出 格式 sed [选项] 命令 文件 sed 选项-f 脚本 文件 返回值 …

Ascend C算子开发(入门)—— 算子开发初体验

文章目录 Ascend C算子开发&#xff08;入门&#xff09;—— 算子开发初体验Host与Device核函数什么是核函数如何编写核函数&#xff1f; 核函数实现例子——Hello World完整核函数泛讲 Ascend C算子开发&#xff08;入门&#xff09;—— 算子开发初体验 Host与Device Host…

Centos挂载yum源

1、查看centos安装后的yum源 [rootlocalhost ~]# ll /etc/yum.repos.d/2、把默认Yum源备份(可选) [rootlocalhost ~]# mkdir /opt/centos-yum.bak [rootlocalhost ~]# mv /etc/yum.repos.d/* /opt/centos-yum.bak/3、将iso镜像上传到虚机上放到该目录下 [rootlocalhost ~]#m…

Android - Windows平台下Android Studio使用系统的代理

这应该是第一篇Android的博文吧。以后应该会陆续更新的。记录学习Android的点点滴滴。 之前也看过&#xff0c;不过看完书就忘了&#xff0c;现在重拾Android&#xff0c;记录学习历程。 为何要用代理 因为更新gradle太慢了。 如何使用系统的代理 先找到系统代理的ip和端口。…

什么是幂等?如何保证接口幂等性?

1、什么是幂等&#xff1f; 幂等其实是在数学中提出的一个概念&#xff0c;对应到程序中&#xff0c;幂等就是说方法被多次重复执行时&#xff0c;所产生的影响和第一次执行时所产生的影响是相同的&#xff08;程序中指的幂等性&#xff0c;其实一般是指业务上幂等&#xff09;…

电脑办公之基础操作(持续更新)

一 常用快捷键 ctrl c 复制(copy)ctrl v 粘贴(paste)ctrl s 保存修改内容windows键d 回到桌面, windows键是左下角附近四个方块或其它类似键 二 鼠标的用法 2.1 左键 左键有单击、双击、长按拖动三种使用方法 单击   用来选中某个文档/文件夹&#xff0c;或定位到某个位…

python实战一:合并多个Excel中数据

看不懂可以跟着视频学一下&#xff0c;关于基础课程项目也可以私聊我&#xff01; 视频源码&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/2055653f735b 之前我们已经学习了如何读取和写入Execl数据&#xff0c;今天我们来用一个实例来进行表格的合并。如下是 2021年…

深度学习100问38:什么是阿达玛乘积

嘿&#xff0c;你知道阿达玛乘积不&#xff1f;这就像一场特别的“元素派对”。 假如有两个像棋盘一样的矩阵 A 和 B。阿达玛乘积呢&#xff0c;就是让这两个矩阵里对应的位置上的元素来一场“亲密接触”。就好比两个队伍的小伙伴一一对应&#xff0c;然后互相做乘法游戏。 …