これが私の観察です:-----> 1.使用場所:サイクリックバリアでは、スレッドは他のスレッドが出力を出すのを待たなければならず、その後すべてのスレッドが処理を再開しなければなりません。したがって、実行が完了した後、各スレッドはawait()メソッドを呼び出して待機します。バリアは、すべてのスレッドが到達したことを検出すると、待機中のすべてのスレッドに通知し、さらに実行を再開できます。バリアはカウントを追跡します。
CountDownLatchでは、単一のメインスレッドがすべてのスレッドが完了するのを待ちます。各スレッドは、実行の完了後にカウントを1つ減らします。カウントが0に達すると、メインスレッドはそれ以上の実行を再開できます。メインスレッドはカウントを追跡します。
Phaser:どちらの場合も、スレッドの数を事前に知っておく必要があります。スレッドを動的に追加/削除することはできません。カウントに達しない場合、カウントを追跡しているスレッドは無限に待機します。Phaserを使用すると、スレッドの数を動的にし、時間とともに変化させることができます。サイクリックバリアに似ています。スレッドはバリアに登録されます。実行完了後、2つのオプションがあります。バリアポイントに到達したことを通知でき、他の人を待たずにPhaserから登録解除できます。2番目のオプションは、他の登録済みスレッドがバリアポイントに到着するのを待つことができるということです。
カウント:CyclicBarrierの作成中に、他のスレッドが完了するのを待機する場合、ワーカースレッドの数にはメインスレッドが含まれません。CountDownLatchを作成する際には、メインスレッドが完了するまで待機するワーカースレッドの数を指定する必要があります。CountDownLatchには、メインスレッドとワーカースレッドの概念があり、ラッチの作成中はメインの待機スレッドはカウントに含まれません。Phaserは、登録されているスレッドの現在の数を返すことができます。
await()の意図:CyclicBarrier :: await()では、メインスレッドを含むすべてのスレッドが等しく、互いに待機します。したがって、await()はすべてのスレッド(ワーカーとメインスレッド)で指定する必要があります。CountDownLatch :: await()はメインスレッドでのみ指定され、他のワーカースレッドがカウントを0にするまでメインスレッドを待機させます。したがって、両方のawait()の内部実装は異なります。Phaserには2つの概念があります::バリアへの到着(arrive()とarriveAndDeregister())と他のスレッドの待機(awaitAdvance(phase_number))。
パーティと待機中のスレッド:CountDownLatchは待機中のスレッドの数を指定できませんが、パーティ(cl.getCount())を指定できます。CyclicBarrierは待機中のスレッドを指定できません。cb.getNumberWaiting()、およびpartys(cb.getParties())
作業責任:countdownlatchのワーカースレッドはcountdown()を実行する必要があり、await()は単一のメインスレッドによって実行されます。CyclicBarrierでは、ワーカースレッドとメインスレッドはすべて、相互にawait()のみを実行します。
再利用: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オブジェクトを再利用できます。
終了イベント後:作成中、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!!" );
}
}