CountDownLatchは便利なツールクラスです。それを使用して、特定の条件が熟した後に1つ以上のスレッドを傍受して実行することができます。その内部コンテンツはカウンターを提供し、ロックを構築するときにカウンターの初期値を指定する必要があり、カウンターの初期値は0より大きくなければなりません。さらに、カウンター値を操作するカウントダウン方法も提供します。カウンターダウンメソッドが呼び出されるたびに、カウンターは1によって減少します。カウンター値が0に減少すると、条件が熟していることを意味し、呼び出すことによってすべてのスレッドがブロックされることを意味します。これは、CountDownLatchの内部メカニズムです。それは非常にシンプルに見えます、それはいくつかのスレッドをブロックし、特定の条件に到達した後にそれらを実行できるようにすることにすぎません。ただし、CountDownLatchには幅広いアプリケーションシナリオがあります。あなたが大きな心を持っていてそれを使う限り、あなたはさまざまなトリックをプレイすることができます。最も一般的なアプリケーションシナリオは、複数のスレッドが同時にタスクを実行できるようにし、すべてのタスクが実行された後に結果をカウントおよび要約することです。次の図は、スレッドをブロックするプロセス全体を動的に示しています。
上記の図は、5つのスレッドが待機方法を呼び出すことによってブロックされていることを示しており、実行を続ける前にカウンター値が0に減少するのを待つ必要があります。カウンターの初期値は、ロックを構築するときに指定され、その後、各コールがカウントダウンメソッドに1回削減されます。次のコードには、CountDownLatch構築方法が投稿されています。
// constructor public countdownlatch(int count){if(count <0)throw new IllegalargumentException( "count <0"); this.sync = new Sync(count); }CountDownLatchには1つのパラメーターコンストラクターのみがあり、カウンターの初期値として0を超える値を渡す必要があります。そうしないと、エラーが報告されます。コンストラクターでは、新しい同期オブジェクトだけを確認し、メンバー変数同期に割り当てることができます。他の同期ツールクラスと同様に、CountDownLatchの実装はAQSに依存しています。AQS共有モードのアプリケーションです。 CountDownLatchは、内部クラスの同期を実装し、AQSによって提供されるほとんどの方法を使用できるようにAQを継承するために使用します。同期の内部クラスのコードを見てみましょう。
// Synchronizerプライベート静的最終クラス同期AbstractQueuedSynchronizer {// constructor sync(int count){setState(count); } //現在の同期状態を取得しますint getCount(){return getState(); } //ロックを取得しようとします//ネガティブ数を返す:現在のスレッドが取得できなかったことを示します1:-1; } //ロック保護されたブールのtryReleaseShared(int leleases){for(;;){//同期状態int c = getState();を取得してください。 //同期状態が0の場合、if(c == 0){return false; } //それ以外の場合は、同期状態を1 int nextc = c-1で減らします。 // CASメソッドを使用して同期状態を更新する場合は(CompareAndsetState(c、nextc)){nextc == 0を返します。 }}}}Syncのコンストラクターが、同期状態の値を渡されたパラメーター値に設定することがわかります。その後、カウントダウンメソッドが呼び出されるたびに、同期状態の値が1だけ削減されます。これはカウンターの実装原則です。 CountDownLatchツールクラスを使用する際に最も一般的に使用される2つのメソッドは、待機方法とCountDownメソッドです。待機方法を呼び出すと、カウンターが0になるまで現在のスレッドがブロックされ、カウントダウンメソッドを呼び出すと、カウンター値が0になるまで1だけ減少します。待機方法の呼び出し方法を見てみましょう。
//現在のスレッドがラッチが0に減少するか、スレッドが中断されるまで待機します。 (thread.interrupted()){new arturnedexception(); } // 1。ロックを取得してみてください(tryacquireshared(arg)<0){// 2。取得が失敗した場合、doacquireshared utteribly(arg)を入力します。 }}スレッドが待機方法を呼び出すと、実際にはAQSのAcquiresharedErtiviliblyメソッドを呼び出します。この方法は、スレッドの中断に応じてロックを取得します。この方法のコードも上に投稿されています。 Acquireshared -Frumpibly Methodでは、最初に、TryAcquiresharedメソッドを呼び出してロックを取得しようとすることがわかります。同期して書き直されたTryAcquiresharedメソッドのロジックがわかります。メソッドの実装ロジックは非常に単純です。これは、現在の同期状態が0であるかどうかを判断するためです。0の場合、RETURN 1はロックを取得できることを意味します。 TryAcquiresharedメソッドが1を返す場合、スレッドは待たずに実行され続けることができます。 -1が返された場合、同期キューでDoacquireshared途中で途切れやすい方法が呼び出されます。これは、待ち合わせ方法を呼び出すと現在のスレッドをブロックするという原則です。カウントダウンメソッドがブロックスレッドを目覚めさせる方法を見てみましょう。
// public public void countdown(){sync.releaseshared(1);} //リリース操作(共有モード)public final booleanリリース(int arg){// 1。ロックをリリースしてみてくださいif(tryreleaseshared(arg)){// 2。リリースが成功した場合は、他のスレッドを覚ます(); trueを返します。 } falseを返します;}リリースシェアされたメソッドがCountdownメソッドで呼び出されていることがわかります。この方法は、AQSの方法でもあります。また、コードを投稿しました。リリースメソッドの最初のことは、ロックをリリースしようとするためにTryReleaseSharedメソッドを呼び出すことです。 TryReleAseSharedメソッドは、AQSの抽象的なメソッドです。その特定の実装ロジックは、サブクラス同期クラスにあります。上記のSyncクラスコードでこの方法を見つけることができます。 tryReleaseSharedメソッドがリリースにtrueを返し、falseを返して障害を解放した場合。同期状態が1減少した後に正確に0の場合にのみtrueを返します。他の場合、falseが返されます。次に、TryReLeaseSharedがtrueを返すと、DoreleaseSharedメソッドがすぐに呼び出され、同期キュー内のすべてのスレッドを目覚めさせます。これは、カウンターを0に減らすためにカウントダウンメソッドが最後に呼び出されるのは、すべてのブロックされたスレッドを目覚めさせる理由を説明します。これらは、CountDownLatchの基本原則です。その使用の例を見てみましょう。
アプリケーションシナリオ:ハッピーランドロードをプレイするときは、3人のプレイヤー全員が到着するのを待つ必要があります。
パブリッククラスプレーヤーはスレッドを拡張します{private static int count = 1;プライベート最終int id = count ++;プライベートカウントダウンラッチラッチ。パブリックプレーヤー(CountDownLatchラッチ){this.latch = latch; } @Override public void run(){system.out.println( "【player" + id + "] entry"); latch.countdown(); } public static void main(string [] args)throws arturnedexception {countdownLatch latch = new CountDownLatch(3); System.out.println( "ゲームが始まり、プレーヤーが入るのを待っています...");新しいプレーヤー(latch).start();新しいプレーヤー(latch).start();新しいプレーヤー(latch).start(); latch.await(); System.out.println( "プレイヤーが到着し、取引を開始..."); }}操作の結果は、すべてのプレイヤーがフィールドに入った後、取引操作を実行する必要があることを示しています。 23行のlatch.await()にコメントし、結果を確認するために比較します。
ラインlatch.await()をコメントした後、すべてのプレイヤーがフィールドに入った後にのみカードを扱い始めることは保証されていません。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。