面試官:你手寫過(guò)堵塞隊(duì)列嗎?我懵了。。
閱讀本文大概需要 5 分鐘。
來(lái)自:blog.csdn.net/qq_38306425/article/details/109332045

1.什么是隊(duì)列

推薦下自己做的 Spring Boot 的實(shí)戰(zhàn)項(xiàng)目: https://github.com/YunaiV/ruoyi-vue-pro
2.什么是堵塞隊(duì)列?

推薦下自己做的 Spring Cloud 的實(shí)戰(zhàn)項(xiàng)目: https://github.com/YunaiV/onemall
3.如何實(shí)現(xiàn)堵塞隊(duì)列?
4.BlockingQueue如何使用?
4.1 BlockingQueue主要方法

4.2 BlockingQueue主要實(shí)現(xiàn)類
ArrayBlockingQueue:ArrayBlockingQueue是基于數(shù)組實(shí)現(xiàn)的,通過(guò)初始化時(shí)設(shè)置數(shù)組長(zhǎng)度,是一個(gè)有界隊(duì)列,而且ArrayBlockingQueue和LinkedBlockingQueue不同的是,ArrayBlockingQueue只有一個(gè)鎖對(duì)象,而LinkedBlockingQueue是兩個(gè)鎖對(duì)象,一個(gè)鎖對(duì)象會(huì)造成要么是生產(chǎn)者獲得鎖,要么是消費(fèi)者獲得鎖,兩者競(jìng)爭(zhēng)鎖,無(wú)法并行。LinkedBlockingQueue:LinkedBlockingQueue是基于鏈表實(shí)現(xiàn)的,和ArrayBlockingQueue不同的是,大小可以初始化設(shè)置,如果不設(shè)置,默認(rèn)設(shè)置大小為Integer.MAX_VALUE,LinkedBlockingQueue有兩個(gè)鎖對(duì)象,可以并行處理。DelayQueue:DelayQueue是基于優(yōu)先級(jí)的一個(gè)無(wú)界隊(duì)列,隊(duì)列元素必須實(shí)現(xiàn)Delayed接口,支持延遲獲取,元素按照時(shí)間排序,只有元素到期后,消費(fèi)者才能從隊(duì)列中取出。PriorityBlockingQueue:PriorityBlockingQueue是基于優(yōu)先級(jí)的一個(gè)無(wú)界隊(duì)列,底層是基于數(shù)組存儲(chǔ)元素的,元素按照優(yōu)選級(jí)順序存儲(chǔ),優(yōu)先級(jí)是通過(guò)Comparable的compareTo方法來(lái)實(shí)現(xiàn)的(自然排序),和其他堵塞隊(duì)列不同的是,其只會(huì)堵塞消費(fèi)者,不會(huì)堵塞生產(chǎn)者,數(shù)組會(huì)不斷擴(kuò)容,這就是一個(gè)彩蛋,使用時(shí)要謹(jǐn)慎。SynchronousQueue:SynchronousQueue是一個(gè)特殊的隊(duì)列,其內(nèi)部是沒(méi)有容器的,所以生產(chǎn)者生產(chǎn)一個(gè)數(shù)據(jù),就堵塞了,必須等消費(fèi)者消費(fèi)后,生產(chǎn)者才能再次生產(chǎn),稱其為隊(duì)列有點(diǎn)不合適,現(xiàn)實(shí)生活中,多個(gè)人才能稱為隊(duì),一個(gè)人稱為隊(duì)有些說(shuō)不過(guò)去。5.手寫堵塞隊(duì)列
/**
?*?@author?yz
?*?@version?1.0
?*?@date?2020/10/31?11:24
?*/
????public?class?YzBlockingQuery?{
????private?Object[]?tab;?//隊(duì)列容器
????private?int?takeIndex;?//出隊(duì)下標(biāo)
????private?int?putIndex;?//入隊(duì)下標(biāo)
????private?int?size;//元素?cái)?shù)量
????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();
????????????//隊(duì)列已滿
????????????while?(size==tab.length){
????????????????System.out.println("隊(duì)列已滿");
????????????????//堵塞
????????????????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("隊(duì)列空了");
????????????????//堵塞
????????????????notEmpty.await();
????????????}
????????????Object?obj=?tab[takeIndex];
????????????//如果到了最后一個(gè),則從頭開(kāi)始
????????????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("生產(chǎn)者生產(chǎn)了:"+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("消費(fèi)者消費(fèi)了:"+take);
????????????}
????????});
????
????????thread1.start();
????????thread2.start();
????}
}
