文章目录
前言
本人是一个刚刚上路的IT新兵,菜鸟!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果这篇文章可以帮助到你,劳请大家点赞转发支持一下!
本篇文章分享的内容主要是阻塞式队列,以及代码模拟实现阻塞式队列。
一、阻塞式队列是什么?
阻塞队列是一种特殊的队列. 也遵守 “先进先出” 的原则。
阻塞队列能是一种线程安全的数据结构, 并且具有以下特性:
- ✨当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素。
- ✨当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素。
阻塞队列的一个典型应用场景就是 “生产者消费者模型”,这是一种非常典型的开发模型。
二、生产者消费者模型
什么是生产者消费者模型
🎉🎉🎉生产者消费者模式就是通过一个容器来解决生产者和消费者的 强耦合 问题。(耦合的大概意思是指模块之间的依赖程度,耦合程度越低越好,避免代码之间牵一发而动全身)想详细了解可以去大佬博客学习,附大佬博客:什么是耦合性?
生产者消费者模型的益处
生产者与消费者直接通讯
这是四个消费者向生产者服务器发出请求,假如是一万个,十万个,一亿个消费者向生产者服务器发出请求,那么服务器还能承受住吗??🦉🦉🦉
因此阻塞式队列就发挥他的作用了。
🧑🏻💻🧑🏻💻🧑🏻💻生产者和消费者彼此之间不直接通讯,而通过阻塞式队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞式队列,消费者不找生产者要数据,而是直接从阻塞式队列里取。
-
🎊🎊阻塞式队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
比如在 “抢演唱会门票” 场景下, 服务器在同一时刻可能会收到大量的支付购票请求,如果直接处理这些支付购票请求,服务器可能扛不住(每个支付购票请求的处理都需要比较复杂的流程). 这个时候就可以把这些请求都放到一个阻塞队列中, 然后再由消费者线程慢慢的来处理每个支付购票请求。 -
🎊🎊阻塞式队列也能使生产者和消费者之间 解耦和。
就比如,饭店后厨里的洗菜工和切菜工,洗菜工只负责洗菜,切菜工只负责切洗好的菜。
洗菜工就是"生产者",切菜工就是"消费者"。
洗菜工不关心切菜工用什么切(能切就行,无论是用菜刀切,用武士刀切,用水果刀切),切菜工也不关心洗菜工用什么洗菜(能洗就行,无论是用凉水洗,用热水洗,用洗菜机洗)。
三、标准库中的阻塞式队列
在 Java 标准库中内置了阻塞队列. 如果我们需要在一些程序中使用阻塞队列, 直接使用标准库中的即可。
🎭BlockingQueue 是一个接口,真正实现的类有 链式存储的LinkedBlockingQueue 与 顺序存储的ArrayBlockingQueue 。
🧑🏻💻 put 方法用于阻塞式的入队列, take 用于阻塞式的出队列。
BlockingQueue 也有 offer, poll, peek 等方法, 但是这些方法不带有阻塞特性。
阻塞式队列实现生产者消费者模型:
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>();
// 生产者模型
Thread thread1 = new Thread(() -> {
int value = 0;
while (true) {
try {
// 入队列
blockingQueue.put(value);
System.out.println("生产者:" + value);
value++;
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 消费者模型
Thread thread2 = new Thread(() -> {
while (true) {
try {
// 出队列
int value = blockingQueue.tak