I am learning about Phaser. While doing so, I came across a problem. Below is the code that I have,
public class RunnableTask implements Runnable {
private Phaser phaser;
public RunnableTask(Phaser phaser) {
this.phaser = phaser;
this.phaser.register(); // Question
}
@Override
public void run() {
// this.phaser.register(); // Question
print("After register");
for (int i = 0; i < 2; i++) {
sleep();
print("Before await" + i + ":");
this.phaser.arriveAndAwaitAdvance();
print("After advance" + i + ":");
}
}
private void sleep() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void print(String msg) {
System.out.println(String.format("%s: %s, time=%s, registered=%s, arrived=%s, unarrived=%s, phase=%s.", msg,
Thread.currentThread().getName(), LocalTime.now(), this.phaser.getRegisteredParties(),
this.phaser.getArrivedParties(), this.phaser.getUnarrivedParties(), this.phaser.getPhase()));
}
}
Sample test for the above
public class TestPhaser {
public static void main(String[] args) {
Phaser phaser = new Phaser();
RunnableTask task = new RunnableTask(phaser);
Thread t1 = new Thread(task, "t1");
Thread t2 = new Thread(task, "t2");
Thread t3 = new Thread(task, "t3");
t1.start();
t2.start();
t3.start();
}
}
Upon executing the above program the output is :
After register: t3, time=22:01:26.636, registered=1, arrived=0, unarrived=1, phase=0.
After register: t2, time=22:01:26.636, registered=1, arrived=0, unarrived=1, phase=0.
After register: t1, time=22:01:26.636, registered=1, arrived=0, unarrived=1, phase=0.
Before await 0:: t3, time=22:01:28.728, registered=1, arrived=0, unarrived=1, phase=0.
Before await 0:: t2, time=22:01:28.728, registered=1, arrived=0, unarrived=1, phase=0.
Before await 0:: t1, time=22:01:28.728, registered=1, arrived=0, unarrived=1, phase=0.
After advance 0:: t1, time=22:01:28.728, registered=1, arrived=0, unarrived=1, phase=3.
After advance 0:: t2, time=22:01:28.728, registered=1, arrived=0, unarrived=1, phase=3.
After advance 0:: t3, time=22:01:28.729, registered=1, arrived=0, unarrived=1, phase=3.
Before await 1:: t2, time=22:01:30.730, registered=1, arrived=0, unarrived=1, phase=3.
Before await 1:: t3, time=22:01:30.730, registered=1, arrived=0, unarrived=1, phase=3.
After advance 1:: t2, time=22:01:30.730, registered=1, arrived=0, unarrived=1, phase=4.
After advance 1:: t3, time=22:01:30.732, registered=1, arrived=0, unarrived=1, phase=5.
Before await 1:: t1, time=22:01:30.730, registered=1, arrived=0, unarrived=1, phase=3.
After advance 1:: t1, time=22:01:30.732, registered=1, arrived=0, unarrived=1, phase=6.
You can see there are lots of discrepancies here. The threads are not advanced in a sequence. Also, there are few phases missing or/and not in a sequence.
When I moved the line of code this.phaser.register() from constructor to the beginning of the run method, the output is :
After register: t1, time=22:10:58.230, registered=3, arrived=0, unarrived=3, phase=0.
After register: t3, time=22:10:58.230, registered=3, arrived=0, unarrived=3, phase=0.
After register: t2, time=22:10:58.230, registered=3, arrived=0, unarrived=3, phase=0.
Before await 0:: t2, time=22:11:00.314, registered=3, arrived=0, unarrived=3, phase=0.
Before await 0:: t1, time=22:11:00.314, registered=3, arrived=0, unarrived=3, phase=0.
Before await 0:: t3, time=22:11:00.314, registered=3, arrived=0, unarrived=3, phase=0.
After advance 0:: t2, time=22:11:00.315, registered=3, arrived=0, unarrived=3, phase=1.
After advance 0:: t3, time=22:11:00.315, registered=3, arrived=0, unarrived=3, phase=1.
After advance 0:: t1, time=22:11:00.315, registered=3, arrived=0, unarrived=3, phase=1.
Before await 1:: t1, time=22:11:02.319, registered=3, arrived=0, unarrived=3, phase=1.
Before await 1:: t2, time=22:11:02.319, registered=3, arrived=0, unarrived=3, phase=1.
Before await 1:: t3, time=22:11:02.319, registered=3, arrived=0, unarrived=3, phase=1.
After advance 1:: t3, time=22:11:02.320, registered=3, arrived=0, unarrived=3, phase=2.
After advance 1:: t2, time=22:11:02.320, registered=3, arrived=0, unarrived=3, phase=2.
After advance 1:: t1, time=22:11:02.321, registered=3, arrived=0, unarrived=3, phase=2.
This looks much better that the threads execution and phases are in a sequence.
Here are my questions:
1) Why there are lots of discrepancies when parties were registered inside the constructor of Runnable?
2) In the second result, the stats for arrived and unarrived are zero (incorrect) at each phase. So, how to obtain the correct numbers for them?
Any help is appreciated.