面試官:你手寫過堵塞隊列嗎?

2021-02-20 服務端思維

點擊上方「服務端思維」,選擇「設為星標」

回復」669「獲取獨家整理的精選資料集

回復」加群「加入全國服務端高端社群「後端圈」

面試官:你好,你先做個自我介紹吧

某人:面試官你好,我叫開局一張嘴面試全靠吹,某某年畢業,畢業自家裡蹲大學,做過某某項目。。。。。。

面試官微微一笑,捋了捋稀疏的頭髮:看你簡歷,你精通多線程?那你手寫過堵塞隊列嗎?

某人心裡出現一萬個問號,堵塞隊列是啥玩意?平時基本都是crud,頂多用多線程跑數據


某人:沒有手寫過。

面試官:哦,那你說下堵塞隊列吧

某人支支吾吾:這個有點忘了

面試官:沒事,那我們下一個。

此處省略一萬字。

面試官扭了扭嚴重負荷的頸椎:先到這裡吧,你先回去等通知。

某人:好的。

不出意外,某人等了一個月,等的望眼欲穿,也沒等到那個期待的電話。

1.什麼是隊列

隊列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。


隊列其實就是跟平時排隊一樣,按照順序來,先排隊的先買到東西,後排隊的後買到東西,排隊的第一個叫隊頭,最後一個叫隊尾,這就是隊列的先進先出,這是和棧最大的區別。

2.什麼是堵塞隊列?

當隊列為空時,消費者掛起,隊列已滿時,生產者掛起,這就是生產-消費者模型,堵塞其實就是將線程掛起。
因為生產者的生產速度和消費者的消費速度之間的不匹配,就可以通過堵塞隊列讓速度快的暫時堵塞,
如生產者每秒生產兩個數據,而消費者每秒消費一個數據,當隊列已滿時,生產者就會堵塞(掛起),等待消費者消費後,再進行喚醒。

堵塞隊列會通過掛起的方式來實現生產者和消費者之間的平衡,這是和普通隊列最大的區別。

3.如何實現堵塞隊列?

jdk其實已經幫我們提供了實現方案,java5增加了concurrent包,concurrent包中的BlockingQueue就是堵塞隊列,我們不需要關心BlockingQueue如何實現堵塞,一切都幫我們封裝好了,只需要做一個沒有感情的API調用者就行。

4.BlockingQueue如何使用?

BlockingQueue本身只是一個接口,規定了堵塞隊列的方法,主要依靠幾個實現類實現。

4.1BlockingQueue主要方法

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.2BlockingQueue主要實現類

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 <= 0) {
new NullPointerException();
}

tab = new Object[tabCount];
notEmpty = reentrantLock.newCondition();
notFull = reentrantLock.newCondition();
}

public boolean offer(Object obj) {
if (obj == null) { throw new NullPointerException(); }
try {
//獲取鎖
reentrantLock.lock();
//隊列已滿
while (size==tab.length){
System.out.println("隊列已滿");
//堵塞
notFull.await();
}
tab[putIndex]=obj;
if(++putIndex==tab.length){
putIndex=0;
}
size++;
//喚醒讀線程
notEmpty.signal();
return true;
} catch (Exception e) {
//喚醒讀線程
notEmpty.signal();
} finally {
reentrantLock.unlock();
}
return false;
}


public Object take(){
try {
reentrantLock.lock();
while (size==0){
System.out.println("隊列空了");
//堵塞
notEmpty.await();
}
Object obj= tab[takeIndex];
//如果到了最後一個,則從頭開始
if(++takeIndex==tab.length){
takeIndex=0;
}
size--;
//喚醒寫線程
notFull.signal();
return obj;
}catch (Exception e){
//喚醒寫線程
notFull.signal();
}finally {
reentrantLock.unlock();
}
return null;
}


public static void main(String[] args) {
Random random = new Random(100);
YzBlockingQuery yzBlockingQuery=new YzBlockingQuery(5);
Thread thread1 = new Thread(() -> {
for (int i=0;i<100;i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
yzBlockingQuery.offer(i);
System.out.println("生產者生產了:"+i);
}
});

Thread thread2 = new Thread(() -> {
for (int i=0;i<100;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object take = yzBlockingQuery.take();
System.out.println("消費者消費了:"+take);
}
});

thread1.start();
thread2.start();
}
}

作者:我真的好討厭我啊

對「服務端思維」有期待,請在文末點個在看

喜歡這篇文章,歡迎轉發、分享朋友圈

相關焦點

  • Chat Top10 | 給面試官手寫一個 Nacos,多少 K?
    看完這篇 HTTP,跟面試官扯皮就沒問題了作者/分享人:cxuan我是一名程式設計師,我的主要程式語言是 Java,我更是一名 Web 開發人員,所以我必須要了解 HTTP,所以本篇文章就來帶你從 HTTP 入門到進階,看完讓你有一種恍然大悟、醍醐灌頂的感覺。
  • 收穫8個Offer,來給大家分享備戰和面試經驗
    但是並不是說碩士就不如本科,而是面試官對碩士的期望值常常會高於你的成長值,導致面試官落差很大,不利於面試過程。面試官可能會覺得相比之下還不如找一個年輕的本科生更划算。如果決定了找工作,那麼就要儘早開始做準備了,尤其是對於非科班出身的同學,需要學習的基礎更多。下面我就分享一下我決定找工作後備戰秋招的準備工作。
  • 面試官:你抄過別人的作業嗎?大學男生機智回答被錄取
    面試官:你抄過別人的作業嗎?大學男生機智回答被錄取面試已經成為了當下畢業生的一個潮流,沒有經過面試的洗禮,都不好意思說自己是職場的一份子。確實現在的職業真的是很難,但在進入一職場的這一個環節。可謂是難上加難,因為現在的面試,不僅會考察面試者學識,而且還會考察面試者的應變能力。面試小技巧:1、在參加面試前,首先要對所應聘的公司要有充分的了解,包括企業文化,公司當前概況以及未來發展方向等。其次要對所應聘職位有充分的了解,包括具體職位所屬部門,職責權限以及職業發展規劃等。
  • 女大學生去面試,面試官要求交往,面試官:不同意你過不了面試!
    過了沒多久,那家公司就邀請胡小姐到這家公司來參加面試,面試的那天是周末,所以那個公司裡只有面試官更一個人,後來鄧某就問了胡小姐的基本情況之後,還加了好友。胡小姐解釋,當時鄧某總是盯著我看,在面試的時候,他跟我講這個公司的老闆非常信任他。我能不能進來,一切都是他說了算。胡小姐還以為鄧某是公司的會計,而她應聘的是會計助理。
  • 面試官:能談談你的缺點嗎?
    1   面試官:能談談你的缺點嗎?   如果你是面試官,你聽完這些缺點是什麼感受呢?   變相誇自己?還是當面試官傻?如果有這樣想法的同學,建議你想好其他臺詞再去面試吧!
  • 【每日一題】(33題)面試官:你對圖論了解多少?(三)
    本文是:【每日一題】(33題)面試官:你對圖論了解多少?(三)每日一題前兩期:【每日一題】(32題)面試官:你對圖論了解多少?(二)【每日一題】(31題)面試官:你對圖論了解多少?•第 14 題:【每日一題】面試官問:談談你對JS對象的創建和引申•第 13 題[每日一題]面試官問:['1', '2', '3'].map(parseInt)輸出,原因,以及延伸?
  • 面試的時候,面試官問你:你還應聘了哪些單位?要說真話嗎
    面試是進入一個公司之前的一大挑戰,相信大家都遇到過很多比較難回答的問題,比如:問你結婚了嗎?其實這些問題背後,都隱含著面試官對你想要了解的方面,而並不是單純的閒聊。「除了我們公司,還應聘哪些公司?」當你遇到這個問題的時候,該怎麼回答呢?回答:我應聘過一些單位了,面試官會不會覺得你太挑了,要回答:我就應聘過這一家,面試官會不會覺得太假了。其實,說真話更能打動人,主要是要清楚自己怎樣的回答才是最恰當!
  • 面試官:拒絕過你的公司,你還會投簡歷嗎?小夥巧妙回應被錄用!
    為需求一份理想的工作,面試求職是一個必經的過程,面試有成功也會有失敗。很多企業也會有長期的招牌需求,有些求職者面試的時候沒有通過,但面試官也會告知他簡歷已經收錄進公司,如果有合適的職位,也會對求職者發出面試邀請。
  • 【別笑】手撕吊打面試官系列面試題
    用js列印一個乘法表這一題面試官考察的是你關於js的列印相關基礎api的熟悉程度,以及基本的數學常識,送分題console.log(`1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94*1=4 4*2=8 4*3=12 4*4=16
  • 面試官讓我手寫算法,HR小姐姐問我米字加一筆是什麼字?怎麼答?
    最後,組長讓他手寫一個md5的實現方法,這一下把求職者難住了。緊接著,HR小姐姐問了他一個問題:米字加一筆是什麼字?求職者一時語塞,沒答出來,面試官只好讓他回去等通知。而且說句實話,即便是再優秀的工程師,也很難在短短幾分鐘內,當著面試官的面寫出md5算法,能把md5算法理清已經算不錯了。面試官之所以需要你當場寫出來,或許並不是為了想看你出洋相,而是為了考查你的邏輯思維能力。
  • 面試官最喜歡問的幾個問題你肯定遇到過!教你如何應對
    在職場中不管你是剛從學校出來的新人,還是摸爬滾打的老人,到了一個新的環境裡避免不了是要過面試官這一關的,面試的表現是取決於能否留在公司的關鍵。下面就說幾個我們在面試中經常遇到的提問,如何做出最正確的應答。
  • 面試官問我「你有男朋友嗎?」這是對我有意思嗎?
    面試官從來不缺奇葩問題,在各種匹敵小學奧數的數學問題之後,又多了一個:你有男朋友嗎?這件事是在一個招聘網站看到的討論帖,當時面試的同學是個應屆生,而面試官是異性,這位同學在描述事件的時候,還問了一句:「難道面試官對我意思嗎?」
  • 阿里面試官:來手寫一下Redis的LRU算法 我當場懵了
    小夥子你好,之前問過了你基礎知識以及一些緩存的常見幾個大問題了,那你能跟我聊聊為啥Redis那麼快麼?哦,帥氣迷人的面試官您好,我們可以先看一下關係型資料庫跟Redis本質上的區別。我可以打個比方麼:我記得有過一個小夥伴微信問過我上下文切換是啥,為啥可能會線程不安全,我是這麼說的,就好比你看一本英文書,你看到第十頁發現有個單詞不會讀,你加了個書籤,然後去查字典,過了一會你又回來繼續從書籤那裡讀,ok到目前為止沒啥問題。
  • 面試官不拿正眼瞅你,那自己還有機會嗎?
    職場面試最尷尬、最窘迫的就是面試的時候自己一直在說話,面試官連瞅一眼都不瞅你,除了盯著桌子上的文案,要不就是眯著眼睛。上一次參加面試的時候,見到了一個耿直哥,耿直哥在旁邊不停的講話,不停的講話,面試官就這樣眯著眼睛閉目養神,說道一半,耿直哥突然不說話了,走到面試官的面前說:你眼睛是不是有毛病啊?如果有毛病的話,抓緊時間去治啊。
  • 面試官問:你談戀愛了嗎?怎麼回答?
    「你談戀愛了嗎?」「你是什麼星座的?」「你是怎麼過來面試的?」「你的校訓是什麼?」
  • 面試結束時問面試官這些問題,一舉驚豔面試官!
    面試官的最後一問並不總是漫不經心的,你也可以抓住這個機會。很多同學經常在面試結尾時遇到這樣的情況,「我的問題就到這裡,你還有什麼問題嗎?」在面試的最後,面試官總是以這個問題來結尾。但這個似乎是客套為主的最後一問,其實並非看起來那麼簡單。
  • 面試臨近結束,面試官問你有什麼問題要問嗎?你說沒有就不對了
    我們在面試過程中時常會遇到很多問題,每個問題都需要你認真思考,快速反應來解答,不要小瞧這些問題,因為面試官詢問的目的遠不止於問題表面,而是從不同的角度來考察你的能力。其中有一個問題很多面試官都喜歡問,尤其是在面試快要結束時,那就是「你有什麼問題要問嗎?」
  • 面試官:除了我們,你還面試其他公司嗎?高情商的人會這樣回答
    當你正跟面試官交談得火熱,hr突然來了一句:「你還面試找過別的什麼工作嗎?」沒經驗的小白肯定會心裡咯噔一下,這不就是送命題嗎!這跟相親對象問你還跟多少個女孩子約會有啥區別?那該不該實話實說呢?會不會給面試官留下不好的印象?
  • 面試官可怕嗎?各個擊破!
    「你最大的缺點是什麼」現在已經不是唯一一個能讓你出局的難題了。下面將介紹當今最常用的一些壓力面試技巧,並教你如何各個擊破。1恐嚇戰術未來的老闆不愛笑,這可不只是你的想像。面試官的恐嚇戰術可能是等你回答完一些問題後,直接針對你的回答發難,或者連珠炮般的問你一串問題,抑或是用挑釁的態度面對你。
  • 面試官:一分鐘怎麼給盲人描述綠色?美女智答
    面試官:一分鐘怎麼給盲人描述綠色?美女智答,真聰明啊!面試者已經成為當前的一個熱門話題,許許多多的畢業生現在已經開始了求職之旅。但是想要在求職者中脫穎而出,可不是一件簡單的事情。現在大家的學歷普遍提高了,大學生甚至是研究生,其實在求職的時候學歷已經不佔優勢了,面試官反而青睞那些思維活躍,能做出快速反應的求職者。面試現在已經成為了,每個職場人必經的一條路了,不經歷職場面試的殺伐,你都不好意思說你是個職場人。