36

1つの例は、CountDownLatchとCyclicBarrierの違いを説明しているトレーナーの1人によって示されています。

CountDownLatch:石を10人で持ち上げることができるので、10人全員が来るのを待つとします。そうすればあなただけが石を持ち上げることができます。

CyclicBarrier:ピクニックに行く予定で、最初に、すべての人が旅を始める場所から、ある共通の場所で会う必要がある場合。

誰かがこれらのコメントに同意するなら、私にいくつかの詳細を教えてください。

これら両方のクラスのsunAPIをすでに読んでいます。しかし、もう少し説明が必要です。

4

12 に答える 12

66

架空の劇場で:

  • 一人だけがプレイを見ることができる場合、それはミューテックスと呼ばれます。
  • N人がプレイを視聴できる場合はセマフォと呼ばれます。演劇中に誰かが劇場を離れた場合、他の人が演劇を見ることができます。
  • すべての人が劇場を離れるまで誰も入場できない場合は、 CountDownLatchと呼ばれます。ここでは、一人一人が自由意志で劇場を離れることができます。
  • すべての人が劇場に入るまで劇が始まらない場合、それはCyclicBarrierと呼ばれます。ここでは、すべての人が席に着き、席を確保するまで、ショーマンはショーを開始できません。プレイが終了すると、同じバリアが次のショーに適用されます。

ここで、人はスレッドであり、遊びはリソースです。

于 2015-09-05T18:21:34.987 に答える
42

主な違いは、CountDownLatchスレッドをウェイターと到着者に分け、使用するすべてのスレッドCyclicBarrierが両方の役割を実行することです。

  • ラッチを使用すると、ウェイターは最後に到着したスレッドが到着するのを待ちますが、それらの到着したスレッドは自分自身を待つことはありません。
  • バリアを使用すると、すべてのスレッドが到着し、最後のスレッドが到着するのを待ちます。

あなたの掛け金の例は、10人全員が石を一緒に持ち上げるのを待たなければならないことを意味します。これはそうではありません。より良い実例は、各学生が試験を提出するのを辛抱強く待つ試験プロンプターです。学生は、試験を終えたら待つ必要はなく、自由に離れることができます。最後の学生が試験を提出すると(または期限が切れると)、プロンプターは待機を停止し、試験を終了します。

于 2012-04-14T18:51:28.723 に答える
18

実際の例すべての答えに実際の例が欠けていることがわかります。これらのクラスをソフトウェア領域で使用する方法のように

  1. CountDownLatch マルチスレッドのダウンロードマネージャー。ダウンロードマネージャーは、ファイルの各部分を同時にダウンロードするために複数のスレッドを開始します(サーバーがダウンロードする複数のスレッドをサポートしている場合)。ここで、各スレッドはインスタンス化されたラッチのカウントダウンメソッドを呼び出します。すべてのスレッドの実行が終了すると、カウントダウンラッチに関連付けられたスレッドが、さまざまな部分で見つかった部分を1つのファイルに統合します。

  2. CyclicBarrier上記 と同じシナリオですが、ファイルがP2Pからダウンロードされたと仮定します。再び複数のスレッドがピースをダウンロードします。ただし、ここでは、ダウンロードしたピースの相互チェックを特定の時間間隔の後に実行する必要があるとします。ここでは、循環バリアが重要な役割を果たします。各時間間隔の後、各スレッドはバリアで待機し、cyclibarrierに関連付けられたスレッドが整合性チェックを実行できるようにします。CyclicBarrierのおかげで、この整合性チェックを複数回実行できます。

適切でない場合は訂正してください。

于 2016-09-23T17:48:19.010 に答える
5

ユースケース1 大きなジョブを10個の小さなタスクに分割し、それぞれがスレッドであるとします。完了したジョブを検討する前に、そのスレッドから10個のタスクが終了するのを待つ必要があります。

したがって、メインジョブイニシエータースレッドは、CountDownLatchを使用されるスレッドの数に初期化し、タスクをスレッドに分散し、メソッドでラッチがゼロになるのを待ちますawait。各エグゼキュータスレッドはcountDown、そのタスクの最後に呼び出します。最後に、すべてのスレッドが終了するとメインスレッドがウェイクアップされるため、ジョブ全体が完了したと見なされます。このシナリオではdoneSignal、CountDownLatchjavadocで説明されているラッチを使用します。

ユースケース2大きなジョブを*m個のタスクに分割し、n個のスレッドに分散させたとします。mは行列の行に対応し、各行について計算する合計があります。その場合、行の合計が処理されるように、各タスクの終了後にスレッドを同期する必要があります。その場合、CyclicBarrierスレッド数nで初期化されたものが、各行の計算の終了を待つために使用されます(実際にはm回)。

両方を比較するために、CountDownLatchは1回だけ使用されることになってCyclicBarrierおり、アルゴリズムがスレッドのセットの同期ポイントを必要とするのと同じ回数だけ使用できます。

于 2012-04-14T18:48:34.463 に答える
4

ACyclicBarrierは再利用可能であるため、ツアーの次のレグに進む前に、全員がウェイポイントで集まるレーシングツアーのようなものです。

于 2012-04-14T18:52:16.960 に答える
4

CountDownLatch: すべてのスレッドに実行させたい場合

何か+カウントダウン

他の待機中の(カウントがゼロに達するのを待つ)スレッド続行できるように、カウントダウンラッチを使用できます。実際にカウントダウンを行った以前のすべてのスレッドはこの状況で続行できますが、latch.countdown()の後に処理される行が、他のスレッドがlatch.countdown()に到達するのを待った後になるという保証はありませんが、のスレッド が待機中のスレッドは、latch.await()がゼロに達した後にのみさらに開始されます。

CyclicBarrier: すべてのスレッドを

何かをする+共通点で待つ+何かをする

(各await呼び出しは、スレッドがさらに続行するための待機時間を短縮します)

CyclicBarrierの機能は、すべてのスレッドでlatch.countdown()を呼び出してからlatch.await()を呼び出すことにより、CountDownLatchによって1回だけ実現できます。

ただし、カウントダウンラッチをリセット/再利用することはできません。

CyclicBarrierを使用した最良の例は、複数のキャッシュ(複数のスレッドによってウォームアップされた)を初期化してから、さらに処理を開始することです。また、同期で他のキャッシュを再初期化したいと思いました。

于 2013-10-10T14:55:38.363 に答える
4

理論上の違い:

CountDownLatchでは、メインスレッドは他のスレッドが実行を完了するのを待ちます。CyclicBarrierでは、ワーカースレッドは互いに実行が完了するのを待ちます。

カウントがゼロになり、ラッチが開いた後は、同じCountDownLatchインスタンスを再利用できません。一方、バリアが壊れたら、バリアをリセットすることでCyclicBarrierを再利用できます。

実際の例:-

CountDownLatch:マネージャーが開発チーム(AとB)間でモジュールを分割し、両方のチームがタスクを完了したときにのみテストのためにそれをQAチームに割り当てたいというITの世界のシナリオを考えてみます。

ここでは、マネージャースレッドがメインスレッドとして機能し、開発チームがワーカースレッドとして機能します。マネージャースレッドは、開発チームのスレッドがタスクを完了するのを待ちます。

CyclicBarrier:マネージャーが開発チーム(AとB)間でモジュールを分割した同じITの世界のシナリオを考えてみましょう。彼は休暇を取り、両方のチームがそれぞれのタスクを完了するのを待って、両方が完了したら、テストのためにQAチームに割り当てます。

ここでは、マネージャースレッドがメインスレッドとして機能し、開発チームがワーカースレッドとして機能します。開発チームのスレッドは、タスクを完了した後、他の開発チームのスレッドを待ちます。

于 2016-05-14T18:55:12.193 に答える
2

CyclicBarrier:Ludo Game APPでは、すべてのプレイヤーがゲームに参加するまで、4人のプレイヤーのゲームを開始することはできません。4人のプレーヤーすべてを別々のスレッドとして想定しましょう。この場合、プレーヤー(スレッド)は他のすべてのスレッド(プレーヤー)がゲームに参加するのを待つ必要があります。ゲームに参加した後、それぞれがawait()メソッドを呼び出します。定義された数のスレッドによってawait()メソッドが呼び出された後でのみ、実行を続行できます。つまり、すべてのプレーヤーがゲームに参加しました。

CountDownLatch:IT会社で4人のメンバーからなるチームに対して調査が行われており、マネージャーはすべての従業員のフィードバックを上級管理職に提出する必要があるとします。このシナリオでは、4人の従業員全員が、フィードバックを提供してcountDown()メソッドを呼び出すスレッドです。すべての従業員がフィードバックを送信しないか、期限に達するまで、マネージャースレッドはawait()メソッドを呼び出して待機する必要があります。マネージャーは、従業員からフィードバックを受け取った後、上級管理職にフィードバックを送信できます。countDownLatchスレッドの場合、お互いを待つ必要はなく、countDown()メソッドを呼び出した後も実行を続行できます。つまり、従業員はプログラムを書き続けるか、フィードバックを送信した後に昼食に行くことができます。

詳細はこちら

于 2021-08-25T10:49:43.543 に答える
1

名前が示すように、循環バリアはサイクルで使用できます。例:私はさまざまな求人ポータルフィードからN個の履歴書を探している会社です。優先度順にソートされたスキルを含むスキルセット配列があります。ex java、c#、pythonの場合。Javaスキルセットに一致するN履歴書を見つけたいのですが、必要な履歴書が見つからない場合はありません。履歴書の中で、次のスキルセットなどをもう一度検索します。

割り当てられたジョブフィードで、それぞれが履歴書をスキャンするワーカーを作成します。両方のワーカーは、ジョブフィードの主要なスキルセット検索から開始します。

検索を実行した後、ワーカーはN個の履歴書が見つかったかどうかを確認します。見つかった場合、ワーカーはバリアをリセットして戻ります。それ以外の場合は、他のワーカーが完了するのを待ちます。それでもN個の履歴書が見つからなかった場合は、スキルセット配列の次のスキルで検索が再開されます。したがって、検索は、新しい循環バリアを作成する必要なしに、再帰的/循環的に呼び出すことができます。

于 2018-02-02T15:31:10.873 に答える
1

CyclicBarrierの場合、私が考えることができる1つのリアルタイムの例。テンポトラベラーに観光客のグループがいると想像してみましょう。1日に訪れる場所は複数あります。テンポドライバーは、x人の観光客がいることを知っています。最初の場所に到達すると、すべての観光客が出て行き、さまざまな時点で戻ってきます。ただし、テンポと旅行者は、すべての観光客が戻るまで待たなければなりません。それらすべてが戻ると、ドライバーは次の場所に進み、同じプロセスが繰り返されます。ここで、CyclicBarrierは観光客の数で初期化されます。各観光客はスレッドのようなもので、戻ったときにCyclicBarrier await()を呼び出して、他のすべての観光客が戻ってくるまで待ちます。今、あなたの考えを聞かせてください

于 2020-04-06T15:46:24.103 に答える
0

これが私の観察です:-----> 1.使用場所:サイクリックバリアでは、スレッドは他のスレッドが出力を出すのを待たなければならず、その後すべてのスレッドが処理を再開しなければなりません。したがって、実行が完了した後、各スレッドはawait()メソッドを呼び出して待機します。バリアは、すべてのスレッドが到達したことを検出すると、待機中のすべてのスレッドに通知し、さらに実行を再開できます。バリアはカウントを追跡します。

CountDownLatchでは、単一のメインスレッドがすべてのスレッドが完了するのを待ちます。各スレッドは、実行の完了後にカウントを1つ減らします。カウントが0に達すると、メインスレッドはそれ以上の実行を再開できます。メインスレッドはカウントを追跡します。

Phaser:どちらの場合も、スレッドの数を事前に知っておく必要があります。スレッドを動的に追加/削除することはできません。カウントに達しない場合、カウントを追跡しているスレッドは無限に待機します。Phaserを使用すると、スレッドの数を動的にし、時間とともに変化させることができます。サイクリックバリアに似ています。スレッドはバリアに登録されます。実行完了後、2つのオプションがあります。バリアポイントに到達したことを通知でき、他の人を待たずにPhaserから登録解除できます。2番目のオプションは、他の登録済みスレッドがバリアポイントに到着するのを待つことができるということです。

  1. カウント:CyclicBarrierの作成中に、他のスレッドが完了するのを待機する場合、ワーカースレッドの数にはメインスレッドが含まれません。CountDownLatchを作成する際には、メインスレッドが完了するまで待機するワーカースレッドの数を指定する必要があります。CountDownLatchには、メインスレッドとワーカースレッドの概念があり、ラッチの作成中はメインの待機スレッドはカウントに含まれません。Phaserは、登録されているスレッドの現在の数を返すことができます。

  2. await()の意図:CyclicBarrier :: await()では、メインスレッドを含むすべてのスレッドが等しく、互いに待機します。したがって、await()はすべてのスレッド(ワーカーとメインスレッド)で指定する必要があります。CountDownLatch :: await()はメインスレッドでのみ指定され、他のワーカースレッドがカウントを0にするまでメインスレッドを待機させます。したがって、両方のawait()の内部実装は異なります。Phaserには2つの概念があります::バリアへの到着(arrive()とarriveAndDeregister())と他のスレッドの待機(awaitAdvance(phase_number))。

  3. パーティと待機中のスレッド:CountDownLatchは待機中のスレッドの数を指定できませんが、パーティ(cl.getCount())を指定できます。CyclicBarrierは待機中のスレッドを指定できません。cb.getNumberWaiting()、およびpartys(cb.getParties())

  4. 作業責任:countdownlatchのワーカースレッドはcountdown()を実行する必要があり、await()は単一のメインスレッドによって実行されます。CyclicBarrierでは、ワーカースレッドとメインスレッドはすべて、相互にawait()のみを実行します。

  5. 再利用:CyclicBarrierは再利用できます。cb.await()は、t1、t2、mainなどの新しいスレッドで機能します。また、新しいスレッドt3、t4およびmainに対するcb.await()の2回目の呼び出しも機能します。Mainは両方の呼び出しで待機します。つまり、バリアが終了した後、システムは自動的に内部でカウントをリセットします(またはreset())。CountDownLatchは再利用できません。--cl.await()は、t1、t2、mainなどの新しいスレッドで機能します。メインスレッドはt1、t2が完了するのを待ちます。ただし、2番目のcl.await()では、新しいスレッドt3、t4を呼び出し、mainは待機しません。セット内のすべてのスレッドがバリアポイントを通過すると、Phaserオブジェクトを再利用できます。

  6. 終了イベント後:作成中、CountDownLatchで終了イベントを指定することはできませんが、CyclicBarrierで指定することはできます。

クラスMyClass{

static class MyThread implements Runnable
{

    long waitTime;
    CyclicBarrier cyclicBarrier;
    CountDownLatch countdownlatch;
    Phaser phaser;


    MyThread(  long waitTime, CyclicBarrier cyclicBarrier, CountDownLatch countdownlatch, Phaser phaser){
        this.waitTime = waitTime;
        this.cyclicBarrier = cyclicBarrier;
        this.countdownlatch = countdownlatch;
        this.phaser = phaser;
        this.phaser.register(); //Note additional step here
    }

    @Override
    public void run() {

            try {

                Thread.sleep(waitTime);

                // Diff 4 -----> countdownlatch worker threads need to do countdown and await is done by one single main thread
                //, cyclicBarrier worker threads await on each other
                countdownlatch.countDown(); 
                cyclicBarrier.await();
                phaser.arriveAndAwaitAdvance();

                System.out.println("cyclicBarrier :: " + 
                        ", name :: " + Thread.currentThread().getName() 
                        + ", parties :: " + cyclicBarrier.getParties() 
                        + ", waiting :: "+ cyclicBarrier.getNumberWaiting()); 

                System.out.println("countdownlatch :: " + 
                            "name :: " + Thread.currentThread().getName()  +
                         ", parties :: "+countdownlatch.getCount() +
                         ", waiting :: " + "No method!!" ); 
                System.out.println("phaser :: " + 
                        "name :: " + Thread.currentThread().getName()  +
                     ", parties :: "+phaser.getRegisteredParties() +
                     ", phase :: " + phaser.getPhase()); 

                phaser.arriveAndAwaitAdvance();
                System.out.println("phaser :: " + 
                        "name :: " + Thread.currentThread().getName()  +
                     ", parties :: "+phaser.getRegisteredParties() +
                     ", phase :: " + phaser.getPhase());

                phaser.arriveAndAwaitAdvance();
                System.out.println("phaser :: " + 
                        "name :: " + Thread.currentThread().getName()  +
                     ", parties :: "+phaser.getRegisteredParties() +
                     ", phase :: " + phaser.getPhase());
                phaser.arriveAndDeregister(); 
                if (phaser.isTerminated()) { 
                    System.out.println("Phaser is terminated"); 
                } 

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

    }

}

public static class MyCBFinishEvent implements Runnable{

    public void run() {

           System.out.println("All threads have reached common barrier point "
                        + ", CyclicBarrrierFinishEvent has been triggered");
           System.out.println("You can update shared variables if any");
    }

}

public static void main(String [] args) throws InterruptedException, BrokenBarrierException{
    //Diff 1 ----- > No finish event can be given in CountDownLatch
    //Diff 5 ------> CyclicBarrier no of worker threads includes main thread, 
    //CountDownLatch is just how many threads, the main waiting thread is not included in count.
    CyclicBarrier cb = new CyclicBarrier(3, new MyCBFinishEvent());
    CountDownLatch cl = new CountDownLatch(2);
    Phaser ph = new Phaser();

    //Diff 2 ----> CountDownLatch cant give num of waiting threads, CyclicBarrier can getNumberWaiting threads
     System.out.println("Start CyclicBarrier - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("Start CountDownLatch - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

    Runnable t1 = new Thread(new MyThread( 10000, cb, cl, ph));
    Runnable t2 = new Thread(new MyThread( 5000, cb, cl,ph));
     Thread tt1 = new Thread(t1, "t1");
     Thread tt2 = new Thread(t2, "t2");
     tt1.start();
     tt2.start();

     //Diff 6 ---- > await meaning Main waits for t1 and t2 to complete, 
     //CyclicBarrier all are equal. each thread including main thread, if it wants to wait has to do await. 
     //CountDownLatch concept of waiting and workers. main thread await waits till other worker threads make count to 0.
     cb.await();
     cl.await();

     System.out.println("End CyclicBarrier call 1 - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("End CountDownLatch call 1 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     System.out.println("main start created t3, t4 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     Runnable t3 = new Thread(new MyThread( 6000, cb, cl,ph));
        Runnable t4 = new Thread(new MyThread( 100, cb, cl,ph));
         Thread tt3 = new Thread(t3, "t3");

         Thread tt4 = new Thread(t4, "t4");

         tt3.start();
         tt4.start();

        //Diff -3 -----> 
         //CyclicBarrier - can be reused, main thread waited for t3, t4 to complete.
         //CountDownLatch - for first cl.await(), main waited... second cl.await() call main did not wait!!! 
         cb.await();
         cl.await();


         System.out.println("End main - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
         System.out.println("end main parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

}

}

于 2019-07-12T07:12:57.930 に答える
0

CountDownLatch:「最良の実例は-人種です」

(たとえば、競馬、自転車レース、カーレースなど、あらゆる種類のレース)

競馬は、を使用して実装できる最高の実例の1つでもありCountDownLatchます。

  1. レース距離は発表または修正されます。(Km /マイル/ヤードでのレース距離)
  2. レースには何頭の馬が参加します。(馬の数)
  3. レースを開始する前に、すべての馬はスタートゲートまたはスタートポイントに到着します。
  4. すべての馬がスタートゲート/スタートポイントに到達すると、レースのみが開始されます。
  5. 信号が送信されると、すべての馬が一度に開始/解放されます。
  6. すべての馬が走り始めます...レース距離を終了する/終了点に到達します。
  7. すべての馬がレース距離を完了するか、フィニッシュポイントに到達したら。
  8. すべての馬の位置/場所のリスト-勝者リストを取得します。
  9. レースの勝者を発表する

CountDownLatchレースの開始と終了には2を使用します。

CountDownLatch start  = new CountDownLatch(1); // Start signal - will be always 1 only once All Horses Reach at Starting Point signal for START RACE.

CountDownLatch finish = new CountDownLatch(horses_Count); // Number of horses participating in Race nothing but Threads/Horses Count.

馬-スレッドに他なりません。

start.await(): 各馬/スレッドが開始ゲート/開始点に到達すると、他の馬/スレッドが開始ゲート/開始点に到達するのを待機します-start.await();

start.countDown():すべての馬/スレッドが開始ゲート/開始点に到達すると、レースを開始するように通知します-start.countDown(); 呼び出さstart.countDown();れるとnotifyAll()、すべての待機中の馬/スレッドがレースを開始します。

finish.await():すべての馬/スレッドがレースを開始すると、メインスレッドはすべての馬/スレッドが終了または完了するのを待つことになります-finish.await();

finish.countDown():各馬/スレッドがレースを終了すると最後の馬/スレッドがカウントをゼロに減らしてからレースが完了/終了しますカウントがゼロになったfinish.countDown(); ときfinish.countDown();に呼び出されると、notify()メインスレッドを待機します-すべての馬/スレッドが終了しました/RACEを完了しました。

于 2020-07-14T19:45:37.547 に答える