你手寫過堵塞佇列嗎?
面試官:你好,你先做個自我介紹吧
某人:面試官你好,我叫開局一張嘴面試全靠吹,某某年畢業,畢業自家裡蹲大學,做過某某專案。。。。。。
面試官微微一笑,捋了捋稀疏的頭髮:看你簡歷,你精通多執行緒?那你手寫過堵塞佇列嗎?
某人心裡出現一萬個問號,堵塞佇列是啥玩意?平時基本都是crud,頂多用多執行緒跑資料
某人:沒有手寫過。
面試官:哦,那你說下堵塞佇列吧
某人支支吾吾:這個有點忘了
面試官:沒事,那我們下一個。
此處省略一萬字。
面試官扭了扭嚴重負荷的頸椎:先到這裡吧,你先回去等通知。
某人:好的。
不出意外,某人等了一個月,等的望眼欲穿,也沒等到那個期待的電話。
1.什麼是佇列
佇列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,和棧一樣,佇列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。
佇列其實就是跟平時排隊一樣,按照順序來,先排隊的先買到東西,後排隊的後買到東西,排隊的第一個叫隊頭,最後一個叫隊尾,這就是佇列的先進先出,這是和棧最大的區別。
2.什麼是堵塞佇列?
當佇列為空時,消費者掛起,佇列已滿時,生產者掛起,這就是生產-消費者模型,堵塞其實就是將執行緒掛起。因為生產者的生產速度和消費者的消費速度之間的不匹配,就可以透過堵塞佇列讓速度快的暫時堵塞, 如生產者每秒生產兩個資料,而消費者每秒消費一個資料,當佇列已滿時,生產者就會堵塞(掛起),等待消費者消費後,再進行喚醒。
堵塞佇列會透過掛起的方式來實現生產者和消費者之間的平衡,這是和普通佇列最大的區別。
3.如何實現堵塞佇列?
jdk其實已經幫我們提供了實現方案,java5增加了concurrent包,concurrent包中的BlockingQueue就是堵塞佇列,我們不需要關心BlockingQueue如何實現堵塞,一切都幫我們封裝好了,只需要做一個沒有感情的API呼叫者就行。
4.BlockingQueue如何使用?
BlockingQueue本身只是一個介面,規定了堵塞佇列的方法,主要依靠幾個實現類實現。
4.1 BlockingQueue主要方法
1.插入資料 (1)offer(E e):如果佇列沒滿,返回true,如果佇列已滿,返回false(不堵塞) (2)offer(E e, long timeout, TimeUnit unit):可以設定等待時間,如果佇列已滿,則進行等待。超過等待時間,則返回false (3)put(E e):無返回值,一直等待,直至佇列空出位置
2.獲取資料 (1)poll():如果有資料,出隊,如果沒有資料,返回null (2)poll(long timeout, TimeUnit unit):可以設定等待時間,如果沒有資料,則等待,超過等待時間,則返回null (3)take():如果有資料,出隊。如果沒有資料,一直等待(堵塞)
4.2 BlockingQueue主要實現類
1.ArrayBlockingQueue:ArrayBlockingQueue是基於陣列實現的,透過初始化時設定陣列長度,是一個有界佇列,而且ArrayBlockingQueue和LinkedBlockingQueue不同的是,ArrayBlockingQueue只有一個鎖物件,而LinkedBlockingQueue是兩個鎖物件,一個鎖物件會造成要麼是生產者獲得鎖,要麼是消費者獲得鎖,兩者競爭鎖,無法並行。
2.LinkedBlockingQueue:LinkedBlockingQueue是基於連結串列實現的,和ArrayBlockingQueue不同的是,大小可以初始化設定,如果不設定,預設設定大小為Integer.MAX_VALUE,LinkedBlockingQueue有兩個鎖物件,可以並行處理。
3.DelayQueue:DelayQueue是基於優先順序的一個無界佇列,佇列元素必須實現Delayed介面,支援延遲獲取,元素按照時間排序,只有元素到期後,消費者才能從佇列中取出。
4.PriorityBlockingQueue:PriorityBlockingQueue是基於優先順序的一個無界佇列,底層是基於陣列儲存元素的,元素按照優選級順序儲存,優先順序是透過Comparable的compareTo方法來實現的(自然排序),和其他堵塞佇列不同的是,其只會堵塞消費者,不會堵塞生產者,陣列會不斷擴容,這就是一個彩蛋,使用時要謹慎。
5.SynchronousQueue:SynchronousQueue是一個特殊的佇列,其內部是沒有容器的,所以生產者生產一個資料,就堵塞了,必須等消費者消費後,生產者才能再次生產,稱其為佇列有點不合適,現實生活中,多個人才能稱為隊,一個人稱為隊有些說不過去。
5.手寫堵塞佇列
我是參照了ArrayBlockingQueue的原始碼寫的,歡迎大家斧正。
/**
* @author yz
* @version 1.0
* @date 2020/10/31 11:24
*/
public class YzBlockingQuery {
private Object[] tab; //佇列容器
private int takeIndex; //出隊下標
private int putIndex; //入隊下標
private int size;//元素數量
private ReentrantLock reentrantLock = new ReentrantLock();
private Condition notEmpty;//讀條件
private Condition notFull;//寫條件
public YzBlockingQuery(int tabCount) {
if (tabCount {
for (int i=0;i {
for (int i=0;i
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3244/viewspace-2807052/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如果讓你手寫個棧和佇列,你還會寫嗎?佇列
- 你見過用命令列寫的簡歷嗎?命令列
- RabbitMQ的佇列模式你真的懂嗎MQ佇列模式
- 全面理解Handler-1:理解訊息佇列,手寫訊息佇列佇列
- 你真的瞭解延時佇列嗎(一)佇列
- 面試官:你使用webpack時手寫過loader,分離過模組嗎?面試Web
- 你知道Redis可以實現延遲佇列嗎?Redis佇列
- 佇列 手算到機算 入門 佇列 迴圈佇列佇列
- 通過佇列實現棧OR通過棧實現佇列佇列
- 陣列手撕堆,你學會了嗎?陣列
- (超詳細)動手編寫 — 棧、佇列 ( Java實現 )佇列Java
- 你真的知道怎麼實現一個延遲佇列嗎?佇列
- 面試官: 你平時用過讀寫鎖嗎?面試
- AQS原始碼深入分析之條件佇列-你知道Java中的阻塞佇列是如何實現的嗎?AQS原始碼佇列Java
- 面試官: 你瞭解過Babel嗎?寫過Babel外掛嗎? 答: 沒有。卒面試Babel
- 「訊息佇列」看過來!佇列
- 【前端面試】同學,你會手寫程式碼嗎?前端面試
- 如何寫一個任務佇列佇列
- 佇列、阻塞佇列佇列
- 寫PHP程式碼你搞過單元測試嗎PHP
- 手擼MQ訊息佇列——迴圈陣列MQ佇列陣列
- 佇列-單端佇列佇列
- 面試官:請簡述一下vue-cli命令列工具,你能自己手寫一個嗎?面試Vue命令列
- 你確定你會寫 Dockerfile 嗎?Docker
- 每日一學:你知道如何在 RabbitMQ 中實現 Work queues工作佇列模式嗎?MQ佇列模式
- 佇列 和 迴圈佇列佇列
- 【佇列】【懶排序】佇列Q佇列排序
- 通過佇列實現批量處理佇列
- 陣列模擬佇列 以及佇列的複用(環形佇列)陣列佇列
- 圖解--佇列、併發佇列圖解佇列
- 單調佇列雙端佇列佇列
- 自己動手實現一個阻塞佇列佇列
- 流高階佇列使用者手冊佇列
- 手擼優先佇列——二叉堆佇列
- 面經手冊 · 第9篇《佇列是什麼?什麼是雙端佇列、延遲對列、阻塞佇列,全是知識盲區!》佇列
- 佇列佇列
- 帶你玩轉RabbitMQ的五種佇列MQ佇列
- 今天你過節了嗎?