In this thread concurrency tutorial we will learn what is java.util.concurrent.Phaser in java with program and examples. Programs to demonstrate usage of Phaser in thread concurrency in java.
Contents of page :
- 1) What is java.util.concurrent.Phaser in java?
- 1.1) Registering/deRegistering the parties in java >
1.2) Phaser’s constructor in java >
- 1.3) Phaser methods in java >
- int register()
- int bulkRegister(int parties)
- int arriveAndDeregister()
- int arrive()
- int arriveAndAwaitAdvance()
- int getPhase()
- boolean isTerminated()
- boolean onAdvance(int phase, int registeredParties)
- 2) Few more quick facts about Phaser in java >
- 3) Example/ Program to demonstrate usage of Phaser in java>
- Let’s discuss output in detail, to get better understanding of Phaser usage in program in java >
- 4) Example/ Program to demonstrate usage of parentPhaser and childPhaser in java >
- 5) Example/ Program to demonstrate usage of how we can override Phaser’s onAdvance method to control number of phase we want to execute in java>
- 5.1) Let’s discuss output in detail, to get better understanding of how we can override Phaser’s onAdvance method to control number of phase we want to execute >
- 6 Application of Phaser in real world >
1) What is java.util.concurrent.Phaser in java?
Phaser is somewhat similar in functionality of CyclicBarrier and CountDownLatch but it provides more flexibility than both of them.
1.1) Registering/deRegistering the parties in java >
In CyclicBarrier we used to register parties in constructor but Phaser provides us flexibility of registering and deRegistering parties at any time.
For registering parties, we may use any of the following -
- constructors, or
- int register(), or
- bulkRegister().
For deRegistering parties, we may use any of the following -
- arriveAndDeregister()
1.2) Phaser’s constructor in java >
- Phaser()
Creates a new phaser with no initially registered parties.
Any thread which want to use this phaser must register it first.
Phaser is created without parent.
Initially phase number is 0.
- Phaser(int parties)
Creates a new phaser with the parties number of registered unarrived parties.
Phaser is created without parent.
Initially phase number is 0.
- Phaser(Phaser parentPhaser, int parties).
Creates a new phaser with the given parent and number of registered unarrived parties.
When the parent is non-null and the parties is greater than 0, this childPhaser is registered with its parent.
parentPhaser does not terminates until childPhaser is not terminated.
/*
*Creates a new phaser (parentPhaser) with no registered unArrived parties
*/
Phaser parentPhaser = new Phaser();
/*
* Creates a new phaser (childPhaser ) with the given parent &
* no registered unArrived parties.
*/
Phaser childPhaser = new Phaser(parentPhaser,0);
Now, parentPhaser does not terminates until childPhaser is not terminated.
|
In below section i have shown usage of this constructor with program.
- Phaser(Phaser parent)
Internally it calls phaser(parent,0).
1.3) Phaser methods in java >
int register()
Adds/Registers a new unarrived party to this phaser. It returns >
- the arrival phase number to which this registration applied.
- If phaser has terminated then value is negative and registration has no effect.
If invocation of onAdvance() method is in progress than before returning this method may await its completion.
If this phaser has a parent, and there were no registered parties with this phaser, this child phaser is also registered with its parent.
int bulkRegister(int parties)
Adds parties number of new unarrived parties to this phaser. It returns >
- the arrival phase number to which this registration applied.
- If phaser has terminated then value is negative and registration has no effect.
If invocation of onAdvance() method is in progress than before returning this method may await its completion.
If this phaser has a parent, and parties is greater than 0, and there were no registered parties with this phaser, this child phaser is also registered with its parent.
int arriveAndDeregister()
Current thread (Party) Arrives and deRegisters from phaser. DeRegistration reduces the number of parties that may be required in future to move to next phase.
Few small questions might come to your mind.
What do you mean by Adds/Registers a new unarrived party to this phaser ?
When we create instance of MyRunnable, we call phaser.register() in constructor, till that time thread (party) on that instance is not started (i.e. party has not arrived), we have only registered phaser.
int arrive()
Method is called to signal that party (current thread) has completed a phase. It returns >
- the arrival phase number.
- If phaser has terminated then value is negative.
If any unregistered party calls arrive() than IllegalStateException is thrown,
When does phase completes?
When number of arrivals = number of registered parties.
Does arrive() cause current thread to wait for other registered threads to complete current phase?
No, arrive() method does not cause current thread to wait for other registered threads to complete current phase. That means current thread can immediately start next phase without waiting for any other registered thread to complete current phase.
int arriveAndAwaitAdvance()
Method is called to signal that party (current thread) has completed a phase.
It returns >
- the arrival phase number.
- If phaser has terminated then value is negative.
If any unregistered party calls arrive() IllegalStateException is thrown,
When does phase completes?
When number of arrivals = number of registered parties.
Now let’s figure out difference between arrive() and arriveAndAwaitAdvance().
Does arriveAndAwaitAdvance() method causes current thread to wait for other registered threads to complete current phase?
Yes, arriveAndAwaitAdvance() method causes current thread to wait for other registered threads to complete current phase. That means current thread can proceed to next phase only when all other threads have completed current phase (i.e. by calling arriveAndAwaitAdvance() method).
int getPhase()
getPhase() method can be used for monitoring purposes. Method returns the current phase number.
For first phase it returns 0, for second phase it returns 1 and so on.
boolean isTerminated()
isTerminated() method returns true if phaser has been terminated.
When is phaser terminated?
when calling arriveAndDeregister() methods has caused the number of registered parties to become 0.
Termination can also be triggered when an onAdvance() method returns true.
boolean onAdvance(int phase, int registeredParties)
We can override the onAdvance( ) method to control number of phases which we want to execute.
phase is the current phase number when we enter onAdvance() method i.e. before advancing to next phase.
registeredParties is the current number of registered parties
Everytime before advancing to next phase overriden onAdvance() method is called and returns either true or false.
If method returns true than phaser is terminated ,or
If method returns false than phaser continues and can advance to next phase.
2) Few more quick facts about Phaser >
- Like a CyclicBarrier, a Phaser can be awaited repeatedly in java.
- Maximum number of parties that could be registered with phaser at a time is 65535, if we try to register more parties IllegalStateException will be thrown in java.
- Phasers may be constructed in tree structures to reduce contention in java.
3) Example/ Program to demonstrate usage of Phaser in java>
import java.util.concurrent.Phaser;
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class PhaserExample {
public static void main(String[] args) {
/*Creates a new phaser with 1 registered unArrived parties
* and initial phase number is 0
*/
Phaser phaser=new Phaser(1);
System.out.println("new phaser with 1 registered unArrived parties"
+ " created and initial phase number is 0 ");
//Create 3 threads
Thread thread1=new Thread(new MyRunnable(phaser,"first"),"Thread-1");
Thread thread2=new Thread(new MyRunnable(phaser,"second"),"Thread-2");
Thread thread3=new Thread(new MyRunnable(phaser,"third"),"Thread-3");
System.out.println("\n--------Phaser has started---------------");
//Start 3 threads
thread1.start();
thread2.start();
thread3.start();
//get current phase
int currentPhase=phaser.getPhase();
/*arriveAndAwaitAdvance() will cause thread to wait until current phase
* has been completed i.e. until all registered threads
* call arriveAndAwaitAdvance()
*/
phaser.arriveAndAwaitAdvance();
System.out.println("------Phase-"+currentPhase+" has been COMPLETED----------");
//------NEXT PHASE BEGINS------
currentPhase=phaser.getPhase();
phaser.arriveAndAwaitAdvance();
System.out.println("------Phase-"+currentPhase+" has been COMPLETED----------");
/* current thread Arrives and deRegisters from phaser.
* DeRegistration reduces the number of parties that may
* be required to advance in future phases.
*/
phaser.arriveAndDeregister();
//check whether phaser has been terminated or not.
if(phaser.isTerminated())
System.out.println("\nPhaser has been terminated");
}
}
class MyRunnable implements Runnable{
Phaser phaser;
MyRunnable(Phaser phaser,String name){
this.phaser=phaser;
this.phaser.register(); //Registers/Add a new unArrived party to this phaser.
System.out.println(name +" - New unarrived party has "
+ "been registered with phaser");
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +
" - party has arrived and is working in "
+ "Phase-"+phaser.getPhase());
phaser.arriveAndAwaitAdvance();
//Sleep has been used for formatting output
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//------NEXT PHASE BEGINS------
System.out.println(Thread.currentThread().getName() +
" - party has arrived and is working in "
+ "Phase-"+phaser.getPhase());
phaser.arriveAndAwaitAdvance();
phaser.arriveAndDeregister();
}
}
/*OUTPUT
new phaser with 1 registered unArrived parties created and initial phase number is 0
first - New unarrived party has been registered with phaser
second - New unarrived party has been registered with phaser
third - New unarrived party has been registered with phaser
--------Phaser has started---------------
Thread-1 - party has arrived and is working in Phase-0
Thread-2 - party has arrived and is working in Phase-0
Thread-3 - party has arrived and is working in Phase-0
------Phase-0 has been COMPLETED----------
Thread-3 - party has arrived and is working in Phase-1
Thread-2 - party has arrived and is working in Phase-1
Thread-1 - party has arrived and is working in Phase-1
------Phase-1 has been COMPLETED----------
Phaser has been terminated
*/
|
3.1) Let’s discuss output in detail, to get better understanding of Phaser usage in program in java >
Note : I have mentioned output in green text.
new phaser with 1 registered unArrived parties created and initial phase number is 0
Phaser phaser=new Phaser(1), Creates a new phaser with 1 registered unArrived parties and initial phase number is 0.
first - New unarrived party has been registered with phaser
second - New unarrived party has been registered with phaser
third - New unarrived party has been registered with phaser
We have created 3 MyRunnable objects and in MyRunnable’s constructor all 3 new unarrived party has been registered with phaser.
--------Phaser has started---------------
main thread has called arriveAndAwaitAdvance() and waiting for another 3 registered parties (Thread-1, Thread-2 and Thread-3) to call arriveAndAwaitAdvance().
Thread-1 - party has arrived and is working in Phase-0
Thread-1 (party) has called arriveAndAwaitAdvance() and waiting for other 2 registered parties to call arriveAndAwaitAdvance()
Thread-2 - party has arrived and is working in Phase-0
Thread-2 (one more party) has called arriveAndAwaitAdvance() and waiting for other 1 registered party to call arriveAndAwaitAdvance()
Thread-3 - party has arrived and is working in Phase-0
Now, all registered parties have called arriveAndAwaitAdvance(), main thread can resume.
------Phase-0 has been COMPLETED----------
As, all registered parties have called arriveAndAwaitAdvance(), main thread has resumed.
Thread-3 - party has arrived and is working in Phase-1
Thread-2 - party has arrived and is working in Phase-1
Thread-1 - party has arrived and is working in Phase-1
After working in phase-1 all the registered threads calls arriveAndAwaitAdvance() and than calls arriveAndDeregister(), now only main thread is registered with phaser.
------Phase-1 has been COMPLETED----------
Main thread has called arriveAndAwaitAdvance() and then called arriveAndDeregister(), now there is no thread registered with phaser.
Phaser has been terminated
As, there is no thread registered with phaser now, phaser has terminated.
4) Example/ Program to demonstrate usage of parentPhaser and childPhaser in java >
Program shows that parentPhaser does not terminates until childPhaser is not terminated.
package PhaserParent;
import java.util.concurrent.Phaser;
public class PhaserParentChildTest {
public static void main(String[] args) {
/*
* Creates a new phaser with no registered unArrived parties.
*/
Phaser parentPhaser = new Phaser();
/*
* Creates a new phaser with the given parent &
* no registered unArrived parties.
*/
Phaser childPhaser = new Phaser(parentPhaser,0);
childPhaser.register();
System.out.println("parentPhaser isTerminated : "+parentPhaser.isTerminated());
System.out.println("childPhaser isTerminated : "+childPhaser.isTerminated());
childPhaser.arriveAndDeregister();
System.out.println("\n--childPhaser has called arriveAndDeregister()-- \n");
System.out.println("parentPhaser isTerminated : "+parentPhaser.isTerminated());
System.out.println("childPhaser isTerminated : "+childPhaser.isTerminated());
}
}
/* OUTPUT
parentPhaser isTerminated : false
childPhaser isTerminated : false
--childPhaser has called arriveAndDeregister()--
parentPhaser isTerminated : true
childPhaser isTerminated : true
*/
|
We created a parentPhaser with no registered unArrived parties. Than we created a childPhaser with the given parentPhaser & no registered unArrived parties.
Then registered childPhaser . Then parentPhaser didn’t terminated until childPhaser was not terminated.
5) Example/ Program to demonstrate usage of how we can override Phaser’s onAdvance method to control number of phase we want to execute in java>
Let me brief you about boolean onAdvance(int phase, int registeredParties) method.
phase is the current phase number when we enter onAdvance() method i.e. before advancing to next phase.
registeredParties is the current number of registered parties in java.
We can override the onAdvance( ) method to control number of phases which we want to execute in java.
Every Time before advancing to next phase overridden onAdvance() method is called and returns either true or false in java.
If method returns true then phaser is terminated ,or
If method returns false then phaser continues and can advance to next phase.
package PhaserOnAdvance;
import java.util.concurrent.Phaser;
/*
* class extending Phaser
*/
public class PhaserOnAdvanceTest extends Phaser{
public PhaserOnAdvanceTest(int parties) {
super(parties);
System.out.println("new phaser with 1 registered unArrived parties"
+ " created and initial phase number is 0 ");
}
/*
* Every time before advancing to next phase overridden
* onAdvance() method is called and returns either true or false.
*/
@Override
protected boolean onAdvance(int phase, int registeredParties) {
System.out.println("onAdvance() method, current phase="+phase);
/*return true after completing phase-1 or
* if number of registeredParties become 0
*/
if(phase==1 || registeredParties==0){
System.out.println("onAdvance() method, returning true, hence phaser will terminate");
return true;
}
else{
System.out.println("onAdvance() method, returning false, hence phaser will continue");
return false;
}
}
public static void main(String[] args) {
//Creates a new phaser with 1 registered unArrived parties and phase-0 created.
PhaserOnAdvanceTest phaser=new PhaserOnAdvanceTest(1);
//Create 3 threads
Thread thread1=new Thread(new MyRunnable(phaser,"first"),"Thread-1");
Thread thread2=new Thread(new MyRunnable(phaser,"second"),"Thread-2");
Thread thread3=new Thread(new MyRunnable(phaser,"third"),"Thread-3");
System.out.println("\n--------Phaser has started---------------");
//Start 3 threads
thread1.start();
thread2.start();
thread3.start();
while(!phaser.isTerminated()){
//get current phase
int currentPhase=phaser.getPhase();
/*arriveAndAwaitAdvance() will cause thread to wait until current phase
* has been completed i.e. until all registered threads
* call arriveAndAwaitAdvance()
*/
phaser.arriveAndAwaitAdvance();
System.out.println("------Phase-"+currentPhase+" has been COMPLETED----------");
}
}
}
class MyRunnable implements Runnable{
Phaser phaser;
MyRunnable(Phaser phaser,String name){
this.phaser=phaser;
this.phaser.register(); //Registers/Add a new unArrived party to this phaser.
System.out.println(name +" - New unarrived party has "
+ "been registered with phaser");
}
@Override
public void run() {
while(!phaser.isTerminated()){
System.out.println(Thread.currentThread().getName() +
" - party has arrived and is working in "
+ "Phase-"+phaser.getPhase());
phaser.arriveAndAwaitAdvance();
//Sleep has been used for formatting output
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/*OUTPUT
new phaser with 1 registered unArrived parties created and initial phase number is 0
first - New unarrived party has been registered with phaser
second - New unarrived party has been registered with phaser
third - New unarrived party has been registered with phaser
--------Phaser has started---------------
Thread-1 - party has arrived and is working in Phase-0
Thread-2 - party has arrived and is working in Phase-0
Thread-3 - party has arrived and is working in Phase-0
onAdvance() method, current phase=0
onAdvance() method, returning false, hence phaser will continue
------Phase-0 has been COMPLETED----------
Thread-2 - party has arrived and is working in Phase-1
Thread-1 - party has arrived and is working in Phase-1
Thread-3 - party has arrived and is working in Phase-1
onAdvance() method, current phase=1
onAdvance() method, returning true, hence phaser will terminate
------Phase-1 has been COMPLETED----------
*/
|
5.1) Let’s discuss output in detail, to get better understanding of how we can override Phaser’s onAdvance method to control number of phase we want to execute in java >
Note : I have mentioned output in green text.
new phaser with 1 registered unArrived parties created and initial phase number is 0
public PhaserOnAdvanceTest(int parties) {
super(parties);
}
Creates a new phaser with 1 registered unArrived parties and initial phase number is 0.
first - New unarrived party has been registered with phaser
second - New unarrived party has been registered with phaser
third - New unarrived party has been registered with phaser
We have created 3 MyRunnable objects and in MyRunnable’s constructor all 3 new unarrived party has been registered with phaser.
--------Phaser has started---------------
main thread has called arriveAndAwaitAdvance() and waiting for other 3 registered parties (Thread-1, Thread-2 and Thread-3) to call arriveAndAwaitAdvance().
Thread-1 - party has arrived and is working in Phase-0
Thread-1 (party) has called arriveAndAwaitAdvance() and waiting for other 2 registered parties to call arriveAndAwaitAdvance()
Thread-2 - party has arrived and is working in Phase-0
Thread-2 (one more party) has called arriveAndAwaitAdvance() and waiting for another 1 registered party to call arriveAndAwaitAdvance()
Thread-3 - party has arrived and is working in Phase-0
Now, all registered parties have called arriveAndAwaitAdvance(), main thread can resume.
onAdvance() method, current phase=0
Everytime before advancing to next phase overridden onAdvance() method is called and returns either true or false.
Hence, we enter onAdvance() method and current phase is 0
onAdvance() method, returning false, hence phaser will continue
onAdvance() method is returning false, hence phaser will continue
------Phase-0 has been COMPLETED----------
Main thread has called arriveAndAwaitAdvance() and then called arriveAndDeregister(), now there is no thread registered with phaser.
Thread-2 - party has arrived and is working in Phase-1
Thread-1 - party has arrived and is working in Phase-1
Thread-3 - party has arrived and is working in Phase-1
onAdvance() method, current phase=1
Hence, we enter onAdvance() method and current phase is 1
if(phase==1 || registeredParties==0){
return true;
}
In if statement phase==1 will satisfy and phaser will return true.
onAdvance() method, returning true, hence phaser will terminate
onAdvance() method is returning true, hence phaser will terminate.
------Phase-1 has been COMPLETED----------
6) Application of Phaser in real world >
Software process management is done in phases.
- First phase could be requirement gathering,
- second could be software development and
- third could be testing.
Second phase will not start until first is not completed, likewise third phase will not start until second is not completed.
SUMMARY>
In this thread concurrency tutorial we learned what is java.util.concurrent.Phaser in java with program and examples. We also wrote programs to demonstrate usage of Phaser in thread concurrency in java.
Having any doubt? or you you liked the tutorial! Please comment in below section.
Please express your love by liking JavaMadeSoEasy.com (JMSE) on facebook, following on google+ or Twitter.
RELATED LINKS>
java.util.concurrent.CountDownLatch >
CountDownLatch in java
Implementation of custom/own CountDownLatch in java
java.util.concurrent.CyclicBarrier >
CyclicBarrier in java
Implementation of custom/own CyclicBarrier in java
Thread concurrency Interviews >