? 作者:小胡_不糊涂
🌱 作者主頁:小胡_不糊涂的個人主頁
📀 收錄專欄:JavaEE
💖 持續更文,關注博主少走彎路,謝謝大家支持 💖
阻塞隊列
- 1. 什么是阻塞隊列
- 2. 標準庫中的阻塞隊列
- 3. 模擬實現
1. 什么是阻塞隊列
阻塞隊列是?種特殊的隊列,遵守 “先進先出” 的原則。
阻塞隊列能是?種線程安全的數據結構,并且具有以下特性:
- 當隊列滿的時候,繼續?隊列就會阻塞,直到有其他線程從隊列中取?元素。
- 當隊列空的時候,繼續出隊列也會阻塞,直到有其他線程往隊列中插?元素。
阻塞隊列的?個典型應?場景就是 “?產者消費者模型”。這是?種?常典型的開發模型。
生產者消費模型:
?產者消費者模式就是通過?個容器來解決?產者和消費者的強耦合問題。
?產者和消費者彼此之間不直接通訊,?通過阻塞隊列來進?通訊,所以?產者?產完數據之后不?等待消費者處理,直接扔給阻塞隊列,消費者不找?產者要數據,?是直接從阻塞隊列?取
- 阻塞隊列就相當于?個緩沖區,平衡了?產者和消費者的處理能力
- 阻塞隊列也能使?產者和消費者之間解耦
2. 標準庫中的阻塞隊列
在 Java 標準庫中內置了阻塞隊列。如果我們需要在?些程序中使?阻塞隊列,直接使?標準庫中的即可。
- BlockingQueue 是?個接?,真正實現的類是 LinkedBlockingQueue
- put ?法?于阻塞式的?隊列,take ?于阻塞式的出隊列
- BlockingQueue 也有 offer, poll, peek 等?法,但是這些?法不帶有阻塞特性
示例:
public static void main(String[] args) throws InterruptedException {BlockingQueue<String> queue=new ArrayBlockingQueue<>(100);queue.put("aaa");//入隊列--有阻塞功能的String elem=queue.take();//出隊System.out.println(elem);//aaa
}
3. 模擬實現
方法:
- 先實現普通隊列–使用數組實現循環隊列,保證實現出入隊列的操作
- 加上線程安全–synchronized
- 加上阻塞隊列
//模擬實現
class MyBlockingQueue{private String[] elems=null;//數組實現隊列private int head=0;//隊首private int tail=0;//隊尾private int size=0;//元素個數private Object loker=new Object();//鎖對象public MyBlockingQueue(int capacity){elems=new String[capacity];}//入隊列public void put(String elem) throws InterruptedException {//有讀寫操作的synchronized (loker) {//隊列滿了,進入阻塞while(size >= elem.length()) {loker.wait();}elems[tail] = elem;//新元素放入tail位置上tail++;//tail=tail%elems.length;if (tail >= elems.length) {tail = 0;//循環對列}size++;//當隊列為空,只要有元素入隊列就喚醒下面的waitloker.notify();}}//出隊列public String take() throws InterruptedException {String tmp =null;synchronized (loker) {//隊列為空while(size == 0) {loker.wait();}tmp = elems[head];head++;if (head >= elems.length) {head = 0;}size--;//當隊列滿了,只要有元素出隊列就喚醒前面的入隊列loker.notify();}return tmp;}
}