多线程——阻塞队列(六)
阻塞队列
阻塞队列是一种特殊的队列. 也遵守 "先进先出" 的原则
阻塞队列是线程安全的,并且有两个特性:
特性:
1、当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素.
2、当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素.
阻塞队列的一个典型应用场景就是 "生产者消费者模型". 这是一种非常典型的开发模型.
优点:
1、有解耦合的作用。
2、削峰填谷。(就相当于一个缓冲区,可以用阻塞队列来限制突然多或者少的情况,不至于导致服务器挂掉)
缺点:
1、上述阻塞队列,并非是简单的数据结构,而是基于这个数据结构的实现的服务器维护,又被部署到单独的主机上。
2、整个系统的结构更复杂了,维护的服务器更多了。
3、效率低了。
生产者消费者模型:
1、生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。
2、阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
3、阻塞队列也能使生产者和消费者之间 解耦。
标准库中的阻塞队列——BlockingQueue
三个阻塞队列的使用
1、BlockingDeque blockingDeque = (BlockingDeque) new ArrayBlockingQueue<>(100);
这是基于数组实现,100是说当前的开的空间。
2、BlockingDeque blockingDeque1 = new LinkedBlockingDeque(100);
这是基于链表实现,100是说当前的开的空间。
3、BlockingDeque blockingDeque2 = (BlockingDeque) new PriorityBlockingQueue<>(100);
这是基于优先级实现,100是说当前的开的空间。
自带的方法:
1、put 方法用于阻塞式的入队列。
2、take 用于阻塞式的出队列
BlockingQueue 也有 offer, poll, peek 等方法, 但是这些方法不带有阻塞特性。
阻塞队列实现
这里我们就使用基于数组实现的阻塞队列来展示。
-
通过 "循环队列" 的方式来实现.
-
使用 synchronized 进行加锁控制.
-
put 插入元素的时候, 判定如果队列满了, 就进行 wait. (注意, 要在循环中进行 wait. 被唤醒时不一定队列就不满了, 因为notify可能是唤醒了其他put的线程).
-
take 取出元素的时候, 判定如果队列为空, 就进行 wait. (也是循环 wait)
第一步:
我们先设置我们使用的成员变量
第二步:
我们创建使用的方法
第三步:
创建实例,使用方法进行操作。