併發編程之阻塞隊列

来源:https://www.cnblogs.com/jihuifeng/archive/2020/07/19/13340535.html
-Advertisement-
Play Games

隊列實質就是一種存儲數據的結構 通常用鏈表或者數組實現 一般而言隊列具備FIFO先進先出的特性,當然也有雙端隊列(Deque)優先順序隊列 主要操作:入隊(EnQueue)與出隊(Dequeue) BlockingQueue 隊列實質就是一種存儲數據的結構 通常用鏈表或者數組實現 一般而言隊列具備FI ...


隊列實質就是一種存儲數據的結構 通常用鏈表或者數組實現 一般而言隊列具備FIFO先進先出的特性,當然也有雙端隊列(Deque)優先順序隊列 主要操作:入隊(EnQueue)與出隊(Dequeue)

BlockingQueue

隊列實質就是一種存儲數據的結構 通常用鏈表或者數組實現 一般而言隊列具備FIFO先進先出的特性,當然也有雙端隊列(Deque)優先順序隊列 主要操作:入隊(EnQueue)與出隊(Dequeue)

1、ArrayBlockingQueue 由數組支持的有界隊列

2、LinkedBlockingQueue 由鏈接節點支持的可選有界隊列

3、PriorityBlockingQueue 由優先順序堆支持的無界優先順序隊列

4、DelayQueue 由優先順序堆支持的、基於時間的調度隊列

BlockingQueue底層依賴ReenTrantLock 和Condition(條件隊列只能在獨占模式下使用,共用模式不能用)(AQS框架實現)

ArrayBlockingQueue

 BlockingQueue<Ball> blockingQueue = new ArrayBlockingQueue<Ball>(1);初始化源碼分析
 public ArrayBlockingQueue(int capacity) {
        this(capacity, false); -------------false預設創建時非公平鎖
    }
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];-------初始化數組
lock = new ReentrantLock(fair);------創建非公平鎖
notEmpty = lock.newCondition(); ---------------初始化了兩個條件隊列,對應兩個條件對列notEmpty ,notFull

notFull = lock.newCondition();
}
// 兩個條件隊列如下圖:


為什麼會有連兩個條件隊列,因為有put(生產者),和take(消費者) 兩個操作 put的時候要看(Notfull)是不是滿了,take(Notempty)是看是不是空了。
put生產者操作源碼解讀
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly(); //----先上來獲取獨占鎖,才能進入下麵的邏輯。
try {
while (count == items.length)
notFull.await(); // 判斷當前隊列是不是已經滿了,如果count == items.length,那麼這個下線程就要入條件隊列等待

enqueue(e);
} finally {
lock.unlock();
}
}
/**
* 加入條件隊列等待,條件隊列入口
*/
public final void await() throws InterruptedException {
//如果當前線程被中斷則直接拋出異常
if (Thread.interrupted())
throw new InterruptedException();
//把當前節點加入條件隊列
Node node = addConditionWaiter();
//釋放掉已經獲取的獨占鎖資源
int savedState = fullyRelease(node);
int interruptMode = 0;
//如果不在同步隊列中則不斷掛起
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
//這裡被喚醒可能是正常的signal操作也可能是中斷
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
/**
* 走到這裡說明節點已經條件滿足被加入到了同步隊列中或者中斷了
* 這個方法很熟悉吧?就跟獨占鎖調用同樣的獲取鎖方法,從這裡可以看出條件隊列只能用於獨占鎖
* 在處理中斷之前首先要做的是從同步隊列中成功獲取鎖資源
*/
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
//走到這裡說明已經成功獲取到了獨占鎖,接下來就做些收尾工作
//刪除條件隊列中被取消的節點
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
//根據不同模式處理中斷
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
/**
* 這裡的判斷邏輯是:
* 1.如果現在不是中斷的,即正常被signal喚醒則返回0
* 2.如果節點由中斷加入同步隊列則返回THROW_IE,由signal加入同步隊列則返回REINTERRUPT
*/
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}

// 這個方法是把條件節點轉運到CLH同步隊列中並把信號量置為初始值0,返迴轉運成功與否標誌。只有把條件節點轉運到同步隊列才又可能被喚醒。
final boolean transferAfterCancelledWait(Node node) {
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
/*
* If we lost out to a signal(), then we can't proceed
* until it finishes its enq(). Cancelling during an
* incomplete transfer is both rare and transient, so just
* spin.
*/
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用示例: $atomic = new Swoole\Atomic(); $serv = new Swoole\Server('127.0.0.1', '9501'); $serv->set([ 'worker_num' => 1, 'log_file' => '/dev/null' ]); // ...
  • 面對可能出現的網路延遲,不可預估的請求流量等情況,設計一個分散式系統,我們通常圍繞系統高可用,數據一致性的目標去規劃和實現,想要完全實現這個目標,卻並非易事。由此,分散式系統領域誕生了一個基本定理,即 CAP 定理,用於指導分散式系統的設計,從系統高可用,數據一致性,網路容錯三個角度將分散式系統的特 ...
  • 在已知的可直接作用於for迴圈的數據類型有以下幾種 第一類 list tuple dict set str 第二類 generator 可直接作用於for迴圈的對象統稱為可迭代對象:Iterable 可利用 isinstance() 判斷一個對象是否是 Iterable 對象 from collec ...
  • 網上關於Spring迴圈依賴的博客太多了,有很多都分析的很深入,寫的很用心,甚至還畫了時序圖、流程圖幫助讀者理解,我看了後,感覺自己是懂了,但是閉上眼睛,總覺得還沒有完全理解,總覺得還有一兩個坎過不去,對我這種有點笨的人來說,真的好難。當時,我就在想,如果哪一天,我理解了Spring迴圈依賴,一定要 ...
  • 關於編程語言中的註釋,其重要性基本上已為大家所共識。 然而關於註釋的規範,這個話題就像我們之前聊過的縮進、終止符和命名方式一樣,眾口難調。 註釋符通常可分為兩種,即行註釋與塊註釋(inline/block),它們在不同的編程語言中的符號可謂讓人眼花繚亂。 比如行註釋符,它至少有以下的 17 種之多( ...
  • 第十四章 高級函數 14.1重載成員函數 ​ 函數可以進行重載,成員函數(成員方法)實質上也是一種函數,所以成員函數也可以進行重載。 程式清單14.1 Rectangle.cpp #include <iostream> class Rectangle { private: int width; in ...
  • 在寫這篇文章時,我是滿懷感激與賞識之情的。 來誇一個人,講一個道理,寫給大家,也是寫給自己。 來自讀者的反饋 先說說事情的經過。 新書出版之後,昨天第一次看到(抱歉看到的比較晚)讀者的反饋。所謂反饋就是在書中留了GitHub的地址,如果書中有錯誤的地方,讀者可以通過該鏈接提交Issues(問題),來 ...
  • 之前只是很模糊的知道其意思:在request scope中,每個request創建一個新的bean;在session scope中,同一session中的bean都是一樣的。但是不知道怎麼用代碼去驗證它,今天可找到驗證它的代碼了。 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...