Friday, May 26, 2023

What is Phaser in Java? When and How to use Phaser? Example Tutorial

Hello guys, if you want to know what is Phaser and when and how to use Phaser in Java then you have come to the right place. Phaser in Java is a synchronization mechanism introduced in Java 7 that allows threads to wait for a certain phase or a set of phases to complete before proceeding further. It is a reusable barrier that allows threads to synchronize and wait for other threads to reach a certain phase before moving ahead. In the past, I have shared the best Concurrency courses and books and also wrote tutorials about popular Java concurrency utility classes like CyclicBarrierCountDownLatchBlockingQueueForkJoinPool, and recently CompletableFuture in this article, you will learn about Phaser, another useful concurrency utility for Java programmers. 
Phaser works by dividing a task into a series of phases, and each thread has to wait until all threads have reached the current phase before proceeding to the next phase. It is similar to the CyclicBarrier and CountDownLatch classes, but it offers more flexibility and functionality.

Phaser is particularly useful in scenarios where multiple threads are performing tasks that need to be synchronized or coordinated. It helps in reducing contention and increasing throughput by allowing threads to work in parallel until they need to be synchronized at a certain phase.



What is Phaser in Java? 

The fundamental goal of Phaser is to allow threads representing one or more stages of an activity to be synchronized. It allows us to create a synchronization object that waits for a certain phase to finish before proceeding. It then moves on to the next phase till that one is finished. It can also be used to synchronize a single phase, and it works similarly to a CyclicBarrier in this sense.

Yeah, I know It sounds like overhead, but let’s see how it is defined and then we can look at the code.


How is Phaser declared?


Phaser myPhaser = new Phaser();


There are multiple constructors for phasers that accept different values like below: 


  1. Phaser myPhaser = new Phaser() - This builds a phaser with no registered parties at first. Only after registering for this phaser may a thread use it.

  2. Phaser myPhaser = new Phaser(int parties) - This establishes a phaser in which each party must have a certain number of threads to progress to the next phase.

  3. Phaser myPhaser = new Phaser(Phaser parent) - For the new object, this defines a parent phaser. The number of parties registered is set to zero.

  4. Phaser myPhaser = new Phaser(Phaser parent, int parties) - This defines a parent phaser for the newly created object as well as the number of parties required to progress to the next phase.


Now, we know that phaser is used for thread synchronization. But, it is not just that. We can also monitor it. While synchronization techniques can only be used by registered parties, any caller can observe the present state of a phaser. There are a total of getRegisteredParties() parties at any given time, with getArrivedParties() arriving at the current phase (getPhase()). 


What is Phaser in Java? When and How to use Phaser? Example Tutorial


The phase progresses when the remaining (getUnarrivedParties()) parties arrive. These techniques' values may represent transitory conditions, making them unsuitable for synchronization control in general. The function toString() { [native code] }() method delivers snapshots of these state inquiries in a format that is easy to observe informally.

Also, Phasers support tiering of phases. To decrease conflict, phasers can be tiered (i.e. built-in tree structures). Phasers with a large number of parties that would normally have high synchronization contention costs might be configured so that groups of sub-phasers share a common parent. Even though it has a higher per-operation overhead, this might substantially boost throughput.

Registration and deregistration of kid phasers with their parents are maintained automatically in a tree of tiered phasers. The child phaser gets registered with its parent if the number of registered parties of a child phaser becomes non-zero (as determined by the Phaser(Phaser,int) function Object() { [native code] }, register(), or bulkRegister(int)).

Now you all must be thinking we know the constructors and what Phaser is, but how are they used? Well no worries, let’s see the code and then understand it!





2. Phaser working code Example

Here is a complete code example of how to use Phaser in Java. You can use this code to try out yourself in your favorite Java IDE like Eclipse or IntelliJIDEA.
import java.util.concurrent.Phaser;

class MyThread implements Runnable{

Phaser myPhaser;
String threadName;

MyThread(Phaser myPhaser, String threadName) {
this.myPhaser = myPhaser;
this.threadName = threadName;
myPhaser.register();
new Thread(this).start();
}

@Override
public void run() {
// phase 1 of our code.
System.out.println("This is Phase one for : "+this.threadName);

// creating a phaser barrier for all threads to sync
myPhaser.arriveAndAwaitAdvance();

try {
Thread.sleep(99);
} catch (InterruptedException e) {
e.printStackTrace();
}

// start new phase of execution, phase 2 of code
System.out.println("This is Phase two for : "+this.threadName);

// creating a barrier for all threads to sync
myPhaser.arriveAndAwaitAdvance();

try {
Thread.sleep(99);
} catch (InterruptedException e) {
e.printStackTrace();
}

// start new phase of execution, phase 3 of code
System.out.println("This is Phase three for : "+this.threadName);

myPhaser.arriveAndDeregister();

}
}
public class MyPhaser {
public static void main(String[] args) {
Phaser myPhaser = new Phaser();
myPhaser.register();

System.out.println("let's start phaser example");

int phase=0;

MyThread cat = new MyThread(myPhaser, "cat");
MyThread dog = new MyThread(myPhaser, "dog");
MyThread elephant = new MyThread(myPhaser, "elephant");

myPhaser.arriveAndAwaitAdvance();

System.out.println("Ending phase one");

myPhaser.arriveAndAwaitAdvance();

System.out.println("Ending phase two");

myPhaser.arriveAndAwaitAdvance();

System.out.println("Ending phase three");
}
}



Output:




Explanation of Code

Now, let’s understand what we did. First of all, there are 4 threads in the system, not 3!

You heard right! 3 threads and 1 main thread. All these threads are associated with a phaser. For associating a thread to a phaser, we use the method “register” of a phaser. This registers the current thread with a current phaser. Now when the execution of all the threads starts, the run method will start for all of them.

Now, the interesting fact is the method “arriveAndAwaitAdvance”. This method waits for other threads by suspending the thread's execution at a phase. The current phase number is returned, or a negative value if the phaser has been terminated. 

Now, observe the output, when the main thread waits on the first arriveAndAwaitAdvance() in the main method while all 3 threads wait in the run method on the first arriveAndAwaitAdvance() method.

These methods are synchronized and they know that all four threads are now waiting on this method, and so, the execution of the program starts further. You can see in the output how the code proceeds. Feel free to try and test different combinations and see the output! Also, note that output may slightly vary depending upon the system and its performance.
 



Important Points about Phaser in Java

Here are some important things to know about Phaser in Java and when it was introduced in Java libraries:
  • Phaser was introduced in java 7 and is a part of the java.util.concurrent library.
  • Like a CyclicBarrier, a Phaser can be awaited repeatedly in java.
  • The maximum number of parties that could be registered with a 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.
  • Phaser is used for easy synchronization between threads and create a barrier before the execution of phases in any code.


When to use Phaser in Java? Use Cases

You can use Phaser when the management of software processes is done in stages. For example, the first process might be gathering requirements, followed by software development, and finally testing.
The second phase will not begin until the first phase has been finished, and the third phase will not begin until the second phase has been completed.



That's all about Phaser in Java. It's one of the important concurrency utils for Java developers and every Java programmer should learn it along with CyclicBarrier, CounntDowLatch, and CompletableFurure as you can use Phaser to build logic in which threads need to wait on the barrier before going to the next step of execution.

You can also create and coordinate multiple phases of execution, reusing a Phaser instance for each program phase and each phase can also have a different number of threads waiting for advancing to another phase.


Other Java Concurrency Articles you may like

  • 10 Java Multithreading and Concurrency Best Practices (article)
  • Difference between atomic, volatile, and synchronized (answer)
  • Difference between CyclicBarrier and CountDownLatch in Java? (answer)
  • How to avoid deadlock in Java? (answer)
  • Top 50 Multithreading and Concurrency Questions in Java (questions)
  • Top 5 Books to Master Concurrency in Java (books)
  • What is happens-before in Java concurrency? (answer)
  • Understanding the flow of data and code in Java program (answer)
  • Is Java Concurrency in Practice still valid (answer)
  • How to do inter-thread communication in Java using wait-notify? (answer)
  • 5 Courses to Learn Java Multithreading in-depth (courses)
  • 10 Advanced books for Experienced Programmers (books)
  • 50+ Thread Interview Questions for Beginners (questions)
  • The Java Developer RoadMap (roadmap)
  • Top 5 skills to Crack Coding interviews (article)
  • 10 Advanced Core Java Courses for Experienced Programmers (courses)

Hope you guys enjoyed the article and learned something new about java. Do try hands-on for Phaser and make sure you understand the behavior and output to further solidify your knowledge about Phaser.

P. S. - If you are new to Java Concurrency and Multithreading and looking for a free online training course to learn Multithreading and Concurrency basics then I also suggest you check out this free Java Multithreading course on Udemy. It's completely free and all you need is a free Udemy account to join this course.

1 comment :

Anonymous said...

What is difference between Phaser and CompletableFuture in Java?

Post a Comment