日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 高频面试题:聊一聊 JUC 下的 LinkedBlockingQueue

發布時間:2025/3/20 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 高频面试题:聊一聊 JUC 下的 LinkedBlockingQueue 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??點擊上方?好好學java?,選擇?星標?公眾號

重磅資訊、干貨,第一時間送達 今日推薦:推薦 8 個常用 Spring Boot 項目個人原創+1博客:點擊前往,查看更多

本文聊一下 JUC 下的 LinkedBlockingQueue 隊列,先說說 LinkedBlockingQueue 隊列的特點,然后再從源碼的角度聊一聊 LinkedBlockingQueue 的主要實現~

LinkedBlockingQueue 有以下特點:

  • 「LinkedBlockingQueue 是阻塞隊列,底層是單鏈表實現的」~

  • 「元素從隊列尾進隊,從隊列頭出隊,符合FIFO」~

  • 「可以使用 Collection 和 Iterator 兩個接口的所有操作,因為實現了兩者的接口」~

  • 「LinkedBlockingQueue 隊列讀寫操作都加了鎖,但是讀寫用的是兩把不同的鎖,所以可以同時讀寫操作」~

LinkedBlockingQueue 隊列繼承了 AbstractQueue 類,實現了 BlockingQueue 接口,LinkedBlockingQueue ?主要有以下接口:

//將指定的元素插入到此隊列的尾部(如果立即可行且不會超過該隊列的容量) //在成功時返回 true,如果此隊列已滿,則拋IllegalStateException。? boolean?add(E?e);?//將指定的元素插入到此隊列的尾部(如果立即可行且不會超過該隊列的容量)? //?將指定的元素插入此隊列的尾部,如果該隊列已滿,? //則在到達指定的等待時間之前等待可用的空間,該方法可中斷? boolean?offer(E?e,?long?timeout,?TimeUnit?unit)?throws?InterruptedException;?//將指定的元素插入此隊列的尾部,如果該隊列已滿,則一直等到(阻塞)。? void?put(E?e)?throws?InterruptedException;?//獲取并移除此隊列的頭部,如果沒有元素則等待(阻塞),? //直到有元素將喚醒等待線程執行該操作? E?take()?throws?InterruptedException;?//獲取并移除此隊列的頭,如果此隊列為空,則返回 null。? E?poll(); //獲取并移除此隊列的頭部,在指定的等待時間前一直等到獲取元素,?//超過時間方法將結束 E?poll(long?timeout,?TimeUnit?unit)?throws?InterruptedException;?//從此隊列中移除指定元素的單個實例(如果存在)。? boolean?remove(Object?o);?//獲取但不移除此隊列的頭元素,沒有則跑異常NoSuchElementException? E?element();?//獲取但不移除此隊列的頭;如果此隊列為空,則返回 null。? E?peek();?

LinkedBlockingQueue 隊列的讀寫方法非常的多,但是常用的是 put()、take()方法,因為它們兩是阻塞的,所以我們就從源碼的角度來聊一聊 LinkedBlockingQueue 隊列中這兩個方法的實現。

先來看看 put()方法,源碼如下:

public?void?put(E?e)?throws?InterruptedException?{if?(e?==?null)?throw?new?NullPointerException();//?預先設置?c?的值為?-1,表示失敗int?c?=?-1;Node<E>?node?=?new?Node<E>(e);//?獲取寫鎖final?ReentrantLock?putLock?=?this.putLock;//?獲取當前隊列的大小final?AtomicInteger?count?=?this.count;//?設置可中斷鎖putLock.lockInterruptibly();try?{//?隊列滿了//?當前線程阻塞,等待其他線程的喚醒(其他線程?take?成功后就會喚醒此處線程)while?(count.get()?==?capacity)?{//?無限期等待notFull.await();}//?新增到隊列尾部enqueue(node);//?獲取當前的隊列數c?=?count.getAndIncrement();//?如果隊列未滿,嘗試喚醒一個put的等待線程if?(c?+?1?<?capacity)notFull.signal();}?finally?{//?釋放鎖putLock.unlock();}if?(c?==?0)signalNotEmpty(); }

put()方法的源碼并不難,非常容易就看懂,put()方法的過程大概如下:

  • 1、先加鎖,保證容器的并發安全~

  • 2、隊列新增數據,將數據追加到隊列尾部~

  • 3、新增時,如果隊列滿了,當前線程是會被阻塞的,等待被喚醒~

  • 4、新增數據成功后,在適當時機,會喚起 put 的等待線程(隊列不滿時),或者 take 的等待線程(隊列不為空時),這樣保證隊列一旦滿足 put 或者 take 條件時,立馬就能喚起阻塞線程,繼續運行,保證了喚起的時機不被浪費offer 就有兩兩種,一種是直接返回 false,另一種是超過一定時間后返回 false~

  • 5、釋放鎖~

其他的新增方法,例如 offer,可以查看源碼,跟put() 方法大同小異,相差不大~

再來看看 take()方法,源碼如下:

public?E?take()?throws?InterruptedException?{E?x;//?默認負數int?c?=?-1;//?當前鏈表的個數final?AtomicInteger?count?=?this.count;//獲取讀鎖final?ReentrantLock?takeLock?=?this.takeLock;takeLock.lockInterruptibly();try?{//?當隊列為空時,阻塞,等待其他線程喚醒?while?(count.get()?==?0)?{notEmpty.await();}//?從隊列的頭部拿出一個元素x?=?dequeue();//減一操作,C比真實的隊列數據大一c?=?count.getAndDecrement();//?c?大于?0?,表示隊列有值,可以喚醒之前被阻塞的讀線程if?(c?>?1)notEmpty.signal();}?finally?{//?釋放鎖takeLock.unlock();}//?隊列未滿,可以喚醒?put?等待線程~if?(c?==?capacity)signalNotFull();return?x; }

take()方法跟 put() 方法類似,是一個相反的操作,我就不做過多的說明了~

以上就是 LinkedBlockingQueue 隊列的簡單源碼解析,希望對你的面試或者工作有所幫助,感謝你的閱讀~

最后,再附上我歷時三個月總結的?Java 面試 + Java 后端技術學習指南,這是本人這幾年及春招的總結,目前,已經拿到了大廠offer,拿去不謝!

下載方式

1.?首先掃描下方二維碼

2.?后臺回復「Java面試」即可獲取

總結

以上是生活随笔為你收集整理的Java 高频面试题:聊一聊 JUC 下的 LinkedBlockingQueue的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。