【JavaEE初阶】阻塞队列

avatar
作者
筋斗云
阅读量:0

目录

📕 引言

🌲阻塞队列是什么

🌳生产者消费者模型

🚩 耦合

📌解耦合(松耦合)

🚩 削峰填谷

🎄Java标准库中的阻塞队列的使用

🚩 标准库实现消费者生产者模型

🍀阻塞队列的模拟实现


📕 引言

🌲阻塞队列是什么

阻塞队列是一种特殊的队列. 也遵守 “先进先出” 的原则.
阻塞队列能是一种线程安全的数据结构, 并且具有以下特性:

  • 当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素

  • 当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素

阻塞队列的一个典型应用场景就是 “生产者消费者模型”. 这是一种非常典型的开发模型

🌳生产者消费者模型

一种解决问题的典型方案(多线程问题).

生产者消费者模式有很多优势,其中两个最主要的是解耦合,削峰填谷

🚩 耦合

耦合是两个或多个模块之间的相互关联。在软件工程中,两个模块之间的耦合度越高,维护成本越高。因此,在系统架构的设计过程中,应减少各个模块之间的耦合度,以提高应用的可维护性

耦合又分为紧耦合(强耦合)和 松耦合(削峰填谷

📌解耦合(松耦合)

🚩 削峰填谷

🎄Java标准库中的阻塞队列的使用

在Java标准库中内置了阻塞队列. 如果需要在一些程序中使用阻塞队列, 直接使用标准库中即可

使用注意事项:

BlockingQueue 是一个接口. 真正实现的类是有以下几种

咱们new 的时候,可选的选项为以下三个:  (数组,链表,堆),实际用的时候哪个都可以

报错的原因:我们要指定一个容量

通过一些方法进行操作:

阻塞队列只需要考虑入队列和出队列即可,阻塞队列没有"取队首元素"操作(也不是没有,只不过没有阻塞功能)。

  • put 方法用于阻塞式的入队列, take 用于阻塞式的出队列

  • BlockingQueue 也有== offer, poll, peek 等方法, 但是这些方法不带有阻塞特性==

注意:put操作要进行异常处理

如果说入队只入了一个元素,出队的时候出两次,那么第二次打印的时候,此时的take就被阻塞到了,一直阻塞到有其他线程往这个队列里面插入元素为止

🚩 标准库实现消费者生产者模型

代码一:(生产慢,消费快)

虽然生产者是每隔1s生产一个元素,但是消费者里面会跟着生产者的节奏进行打印,消费者没有sleep,take自带的阻塞特性,也使消费者处于一个比较慢的速度进行消费。

代码二:(生产快,消费慢)

一瞬间就生产了1000个元素,此时队列就满了,要想在生产元素只能消费一个元素之后,才能生产一个元素......谁慢,另一个就将就谁

链表也能够起到阻塞,通过capacity来控制。

🍀阻塞队列的模拟实现

这里我们又两种结构可以选择,一种是链表的,另一种是数组的形式实现

这里选择的是用数组的形式进行模拟实现

首先我们是通过"循环队列",在数据结构部分已经实现过!

步骤:

  • 写一个普通的队列
  • 再加上线程安全
  • 引入阻塞

普通队列:(入队,出队)

线程安全:(加锁以及针对变量的内存可见性和指令重排序)

引入阻塞:(队列满进行阻塞,队列空进行阻塞)

注意要确保加锁中的的对象和你调用wiat的对象,以及调用notify的对象是一致的。

此时呢代码还有点小小的问题:

在 wait 源码中注释说,wait 不仅仅会被 notify 和 notifyAll 唤醒,也可能会被其他线程唤醒,比如 interrupt。所以建议我们使用 wait 的时候搭配 while 来使用。

代码:(生产慢,消费快)

生产快,消费慢将sleep换到消费者即可,这里就不再演示了。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!