I stumbled upon a doubt regarding a difference between CyclicBarrier and Phaser utilities in Java concurrent package.
I understand that CyclicBarrier allows group of threads to wait until all threads arrive at a specific point. Phaser also do same but it supports multiple phases. I also understand that, a CyclicBarrier can be reused. I think this reuse facility makes its function same as Phaser.
Consider following programs:
Testing Phaser :
import java.util.concurrent.Phaser;
public class PhaserTest {
public static void main(String[] args) {
Phaser p = new Phaser(3);
Thread t1 = new Thread(() -> process(p), "T1");
Thread t2 = new Thread(() -> process(p), "T2");
Thread t3 = new Thread(() -> process(p), "T3");
t1.start();
t2.start();
t3.start();
}
private static void process(Phaser p) {
try {
System.out.println("Started Phase 1: "+Thread.currentThread().getName());
p.arriveAndAwaitAdvance();
System.out.println("Finished Phase 1: "+Thread.currentThread().getName());
System.out.println("Started Phase 2: "+Thread.currentThread().getName());
p.arriveAndAwaitAdvance();
System.out.println("Finished Phase 2: "+Thread.currentThread().getName());
} catch(Exception e) {}
}
}
Output:
Started Phase 1: T1
Started Phase 1: T2
Started Phase 1: T3
Finished Phase 1: T3
Started Phase 2: T3
Finished Phase 1: T1
Finished Phase 1: T2
Started Phase 2: T2
Started Phase 2: T1
Finished Phase 2: T2
Finished Phase 2: T3
Finished Phase 2: T1
Testing CyclicBarrier:
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier cb = new CyclicBarrier(3);
Thread t1 = new Thread(() -> process(cb), "T1");
Thread t2 = new Thread(() -> process(cb), "T2");
Thread t3 = new Thread(() -> process(cb), "T3");
t1.start();
t2.start();
t3.start();
}
private static void process(CyclicBarrier cb) {
try {
System.out.println("Started Phase 1: "+Thread.currentThread().getName());
cb.await();
System.out.println("Finished Phase 1: "+Thread.currentThread().getName());
System.out.println("Started Phase 2: "+Thread.currentThread().getName());
cb.await();
System.out.println("Finished Phase 2: "+Thread.currentThread().getName());
} catch(Exception e) {}
}
}
Output:
Started Phase 1: T1
Started Phase 1: T2
Started Phase 1: T3
Finished Phase 1: T3
Started Phase 2: T3
Finished Phase 1: T1
Started Phase 2: T1
Finished Phase 1: T2
Started Phase 2: T2
Finished Phase 2: T2
Finished Phase 2: T3
Finished Phase 2: T1
In PhaserTest and CyclicBarrierTest, next phase is not started until all parties arrive/completes the previous phase.
So, what's the benefit of having Phaser ?
Phaser comes from JSR-166
When comparing phasers to existing Java features, it is explained that similar functionality to the CyclicBarrier class is supported (introduced in Java 5), but phasers are inherently more flexible:
The [java.util.concurrent] CyclicBarrier class supports periodic barrier synchronization among a set of threads. Unlike Phasers, however, CyclicBarriers do not support the dynamic addition or removal of threads; nor do they support one-way synchronization or split-phase operation. One of the main motivators for exploring additional barrier implementations was not just to have increased flexibility, but also to increase performance and scalability of the barrier synchronization concept:
Performance results obtained from a portable implementation of phasers on three different SMP platforms demonstrate that they can deliver superior performance to existing barrier implementations, in addition to the productivity benefits that result from their generality and safety properties.
full explanation here: https://www.infoq.com/news/2008/07/phasers
Also another comparing article defining Phaser
as CyclicBarier+CountdownLatch
:
http://flex4java.blogspot.com/2015/03/why-and-how-to-use-phaser-in-java.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With