java阻塞队列使用场景(java阻塞队列生产消费者)

java阻塞队列使用场景(java阻塞队列生产消费者)p id main toc strong 目录 strong p 一 了解阻塞队列 1 什么是阻塞队列 2 应用场景 3 标准库的阻塞队列 二 模拟实现阻塞队列 1 实现普通队列 2 实现线程安全 3 实现阻塞功能 4 优化 阻塞队列 也是一种先进先出 的队列

大家好,我是讯享网,很高兴认识大家。



 <p id="main-toc"><strong>目录</strong></p> 

讯享网

一、了解阻塞队列

1、什么是阻塞队列

2、应用场景

3、标准库的阻塞队列

二、模拟实现阻塞队列

1、实现普通队列

2、实现线程安全

3、实现阻塞功能

4、优化


阻塞队列也是一种先进先出的队列,但是它还具有以下特性:

(1)线程安全的队列;

(2) 带有阻塞功能

(a) 如果队列满,继续入队列时,入队列操作就会阻塞,直到队列不满才能完成入队列;

(b) 如果队列空,继续出队列时,出队列操作就会阻塞,直到队列不空才能完成出队列。

阻塞队列的典型应用场景:生产者消费者模型

        生产者消费者模型是一种常见的多线程协调工作的模式:生产者和消费者之间通过阻塞队列进行通讯,生产者生产出数据不用等待消费者来处理,而是会直接放入到阻塞队列中;消费者也不找生产者索要数据,而是直接从阻塞队列中取。

类似于我们去超市买东西:老板作为“生产者”,他把商品放在货物架上让我们自己拿,我们作为“消费者”,也不需要直接去找老板要商品,而是直接去相应的货物架上拿它就行,这个货物架就相当于“交易场所”

如果每个逛超市的人都去找老板说:“老板,我要一个xxx”,那么老板就会非常忙,放在代码中,就是会产生严重的锁冲突。


讯享网

 生产者消费者模型的作用:

(1) 有利于代码“解耦合”

生产者不用关心消费者的存在,消费者也不需关心生产者的存在,通过阻塞队列可以降低二者的关联关系。

(2) “削峰填谷”

阻塞队列相当于一个“缓冲区”,平衡了生产者和消费者的处理能力。

标准库中的阻塞队列是一个接口:BlockingQueue

实现该接口的类:

类名说明LinkedBlockingQueue<>基于链表的阻塞队列LinkedBlockingDeque<>基于链表的双端阻塞队列LinkedTransferQueue<>基于链表的无界阻塞队列ArrayBlockingQueue<>基于顺序表的阻塞队列PriorityBlockingQueue<>带有优先级功能的阻塞队列

入队列方法:put(E e)

出队列方法:take()

注意:

(1) offer(E e)方法也可以入队列,但是这个方法不具有阻塞功能。

(2) 阻塞队列无法阻塞式的查看队首元素,只能先取出队首元素,查看之后再放入队列中。

阻塞队列的简单使用:

讯享网

进程此时并没有结束,因为主线程还在阻塞等待... 

首先我们使用顺序表的方式简单实现一个队列:

 

我们刚才实现的puttake方法的几乎每一行代码都涉及到读写操作,所以在多线程环境下,这种非原子操作一定是不安全的,我们需要对这两个方法进行加锁,并用volatile修饰相应的变量,来保证线程安全:

讯享网

注意:两个方法中加锁的对象必须是同一个对象 。

我们需要实现两个阻塞功能:

(1) 队列满,继续入队列会阻塞,直到有元素出队;

(2) 队列空,继续出队列会阻塞,直到有元素入队。

可以使用waitnotify来进行线程阻塞和唤醒线程的操作:

 

两个方法中的waitnotify会相互唤醒:

虽然我们刚才实现了阻塞功能,但是等待中的线程如果被唤醒后发现队列还是空或满的状态,那么继续执行代码仍然会出错,比如通过interrupt方法唤醒等待中的线程…

所以当线程被唤醒时,我们需要再次判断队列是否为空或满的状态,如果是,则继续等待,如果不是,则执行后面的逻辑:

讯享网

if条件判断换成while循环判断即可解决上述问题

以上就是模拟实现阻塞队列的最终版本

小讯
上一篇 2025-04-15 12:59
下一篇 2025-05-28 14:58

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/186321.html