ディレクトリ
1.LinkedBlockingQueueはじめに
1.1BlockingQueueインタフェース
1.2LinkedBlockingQueue
1.3LinkedBlockingQueue原則とデータ構造
2.LinkedBlockingQueueソースコード解析
2.1作成
2.2put方法
2.3take方法
1.LinkedBlockingQueueはじめに
1.1BlockingQueueインタフェース
ArrayBlockingQueueと同じように、LinkedBlockingQueueもBlockingQueueのインターフェイスを実現しました。
1.2LinkedBlockingQueue
LinkedBlockingQueue
LinkedBlockingQueueは、一方向のブロッキングキューリンクリストの実装です。
LinkedBlockingQueue容量の大きさは、過度の拡張キューを防ぐために、作成時に指定することができます。キューの容量が指定されていない場合、容量Integer.MAX_VALUEでのデフォルトサイズ。
1.3LinkedBlockingQueue原則とデータ構造
説明:
リストの(01)ヘッドがヘッダです。データが除去されると、デキュー、先頭にヘッダから除去されます。
リストの最後の(02)は、テーブルの終わりです。新しいデータは、最後のエンキューからテーブルの最後に挿入されている場合。
(03)リストの実際のサイズは、このリストに含まれるノードの、すなわち数を数えます。
(04)の容量は、リストの作成時に指定されているリストの容量です。
(05)putLockをロックに挿入され、takeLockロックが除去され、notEmpty「非空の状態」は、notFullは「条件の下で。」それらを介して同時実行制御リストについて。
「挿入」と「削除(DELETE)」の操作が異なるロックを使用しているため、「リソースの競合にマルチスレッドの排他的アクセス」の実現にLinkedBlockingQueue。挿入操作の場合は、「挿入ロックputLock」によって同期;アンロード動作のために、「ロックtakeLockを取得」によって同期。
2.LinkedBlockingQueueソースコード解析
2.1作成
公共 LinkedBlockingQueue(int型の容量){ 場合(容量<= 0)スロー 新しい(、IllegalArgumentExceptionを)。 この .capacity = 能力; 最後 =頭= 新しいノード<E>(ヌル); }
// デフォルトを作成するときに指定されていないキューの容量は、Integer.MAX_VALUEである プライベート ファイナル int型の容量; // キュー内の要素の数 プライベート 最終のAtomicIntegerのCOUNT = 新新のAtomicInteger(); // リスト(チームのヘッド)のヘッド 一過ノード<E> ヘッド; // リスト(尾)の終わり プライベート 過渡ノード<E> 最終; // 「delete要素」ロックを制御するための「非空の状態」と対応するtakeLock notEmpty プライベート 最終 ReentrantLockのtakeLockの= 新しい新しいReentrantLockのの(); プライベート 最終条件条件notEmpty =用takeLock.newCondition(); //「添加元素」putLockとnotFull「条件下」は、対応するロック制御のための 専用 最終 ReentrantLockのputLockの= 新しい新; ReentrantLockの()の プライベートの 最終状態の状態notFull putLock.newCondition =()のために、
静的 クラスノード<E> { E項目。 ノード <E> 次; ノード(E X){アイテム = X。} }
2.2 putメソッド
// プット方法:若队列满、待っ直到队列有空闲 公共 のボイドプット(E e)はスローInterruptedExceptionある{ 場合(E == nullの)スロー 新しい(NullPointerExceptionが)。 // 注:すべてのPUT /テイクの/ etc大会は地元のVARをあらかじめ設定することで // 設定しない限り、失敗したことを示すために、カウントマイナスを保持します。 int型、C = -1 ; ノード <E>ノード= 新しいノード<E> (E)。 最終 ReentrantLockのputLockは= この.putLockと、 最終のAtomicInteger数は= この.countを。 //ロックを取得する putLock.lockInterruptibly(); 試み{ // キューが満杯である場合、現在の(プロデューサー)notFull待機スレッドがブロックされて いる間(count.get()== 容量){ notFull.await(); } // 要素にチーム エンキュー(ノード); // 1「キューの要素数」、および「オリジナルの要素数」への復帰 C = count.getAndIncrement(); // キューの後にチームに要素がまだフル、ウェイクアップ待ちの場合notFull(プロデューサー)スレッド上の IF(C + 1 < 容量) notFull.signal(); } 最後に{ // リリースロック putLock.unlock(); } //任意の元キュー要素の数が0、チームにその要素である場合には、ウェイクアップnotEmptyを待っている(消費者)スレッド IF(C == 0 ) signalNotEmpty(); } プライベート 無効エンキュー(ノード<E> ノード){ // アサートputLock.isHeldByCurrentThread(); // アサートlast.next == NULL; 最後= last.next = ノード; } プライベート ボイドsignalNotEmpty(){ 最終 ReentrantLockの= takeLockのこの.takeLock; takeLock.lock()。 トライ{ notEmpty.signal(); } 最後に{ takeLock.unlock(); } }
2.3テイク方法
// メソッドを取る:キューが空の場合、待機を待ち行列が空でなくなるまで 公共 Eのテイクを()スローInterruptedExceptionある{ E Xを; int型 C = -1 ; 最終のAtomicIntegerのCOUNT =のこの.count; 最終 ReentrantLockの= takeLockのこの.takeLock; // GETロック takeLock.lockInterruptibly(); 試みは{ // キューが空である場合、スレッド上の電流(消費者)はnotEmptyを待機するのをブロック しながら(count.get()== 0 ){ notEmpty.await(); } // 要素のうちチーム X- = デキュー(); //「キュー内の要素の数」-1、および「オリジナルの要素数」への復帰 C = count.getAndDecrement(); // もし、チームの要素の後、まだキューに残っている要素、notEmptyをきっかけに待機している(消費者)スレッド IF(C> 1 ) notEmpty.signal(); } 最後に{ // リリースロック takeLock.unlock(); } // デキュー後に元のキューが満杯である場合、素子、notFullにウェイクアップ待機(プロデューサー)スレッド IF(C == 容量) signalNotFull(); 戻りX; } プライベートEデキュー(){ // アサートtakeLock.isHeldByCurrentThread(); // アサートhead.item == NULL; ノード<E> H =頭; ノード <E>第= h.next。 h.next = H; // ヘルプGCの ヘッド= 最初; E、X = first.item。 first.item = nullを。 戻り値は、X; } プライベート ボイドsignalNotFull(){ 最終 ReentrantLockのputLockは= この.putLockと、 putLock.lock(); 試す{ notFull.signal()。 } 最後に{ putLock.unlock()。 } }