1. What is Phaser
jdk7 adds a tool class for multi-stage synchronization control, which contains the related functions of CyclicBarrier and CountDownLatch, which are more powerful and flexible than them.
According to the understanding of Phaser phase coordinator, Phaser is applicable to tasks cooperated by multiple threads. It is divided into multiple phases. Each phase can have any participant, and threads can register and participate in a phase at any time; When all tasks in a phase are successfully completed, Phaser onAdvance() is called, and then Phaser releases the waiting thread and automatically enters the next phase. This cycle continues until the Phaser no longer contains any participants.
2. Phase API description
- Construction method
- Phaser(): number of participating tasks 0
- Phase (int parties): Specifies the initial number of participating tasks
- Phaser(Phaser parent): Specifies the parent phaser. The child object is added to the parent object as a whole. When there is no participant in the child object, it will be deregistered from the parent object automatically
- Phase (phase parent, int parties): a method that integrates the above two methods
- Method of increasing or decreasing the number of participating tasks
- int register(): add a number to return the current phase number
- int bulkRegister(int parties): increase the specified number and return the current phase number
- int arriveAndDeregister(): reduce the number of tasks and return the current phase number
- Arrival waiting method
- int arrive(): upon arrival, the task is completed, and the current phase number is returned
- int arriveAndAwaitAdvance(): wait for other tasks to arrive after arrival, and return the arrival phase number
- int awaitAdvance(int phase): wait in the specified phase (it must be the current phase to be valid)
- int awaitAdvanceInterruptibly(int phase)
- int awaitAdvanceInterruptibly(int phase , long timeout, TimeUnit unit)
- Phase arrival trigger action
- Protected Boolean onadvance (int phase, int registeredparties): similar to the trigger command of CyclicBarrier, the phase arrival action is added by rewriting this method
- Other APIs
- void forceTermination(): forced termination
- boolean isTerMinated(): judge whether to end
- void getPhase(): get the current phase number
- Note: the maximum number of registered tasks allowed for a single Phaser instance is 65535. If the number of participating tasks exceeds, the parent-child Phaser tree can be used
3. Phaser schematic diagram

4. Phaser example
Scene: the company organizes an outing. Everyone sets out from home to the company. When everyone arrives, they set out to play in the park, then gather at the gate of the park, and then go to the restaurant. When everyone arrives, they begin to eat. Some employees are busy during the day and choose to have dinner at night, while others are busy at night and only participate in daytime activities. Programming simulation.
- In the first stage, 5 people were gathered in the company and the number of tasks was 5. They went to the park to play.
- In the second stage, they gathered at the gate of the park. Two people went home from the park on their own because they had something to do at night; Then 3 people go to the restaurant, which is to reduce the number of participants, and the number of tasks becomes 3
- In the third stage, the restaurant gathers, and another 4 people participate in the dinner. This is to increase the number of participants, and the number of tasks becomes 7
import java.util.Random; import java.util.concurrent.Phaser; public class MultipleStartTogetherPhserDemo { Random rd = new Random(); int bound = 5000; public void step1Task() throws InterruptedException { // After a period of time, arrive at the company Thread.sleep(rd.nextInt(bound)); System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "Arrive at the company!"); } public void step2Task() throws InterruptedException { System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "Let's go to the park..."); // After playing for some time, gather at the gate of the park Thread.sleep(rd.nextInt(bound)); System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "Finish the park!"); } public void step3Task() throws InterruptedException { System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "Let's go to the restaurant..."); // After playing for some time, gather at the gate of the park Thread.sleep(rd.nextInt(bound)); System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "Get to the restaurant!"); } public void step4Task() throws InterruptedException { System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "Start eating..."); // After playing for some time, gather at the gate of the park Thread.sleep(rd.nextInt(bound)); System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "go back home"); } public static void main(String[] args) { // Create a phase coordinator object, override onAdvance method, and add phase arrival processing logic final Phaser ph = new Phaser() { protected boolean onAdvance(int phase, int registeredParties) { int staffs = registeredParties - 1; switch (phase) { case 0: System.out.println("Everyone has arrived at the company. Let's go to the park! Number:" + staffs); break; case 1: System.out.println("Everybody go to the park gate and go to the restaurant! Number:" + staffs); break; case 2: System.out.println("Everyone has arrived at the restaurant and started to eat! Number of people:" + staffs); break; } // Judge whether there is only one participant left in the main thread. If yes, return true and the stage coordinator terminates. return registeredParties == 1; } }; // Increase the number of tasks to allow the main thread to participate in the whole process ph.register(); final MultipleStartTogetherPhserDemo job = new MultipleStartTogetherPhserDemo(); // Let 3 threads participate in the whole process for (int i = 0; i < 3; i++) { // Increase the number of participating tasks ph.register(); new Thread(new Runnable() { @Override public void run() { try { job.step1Task(); ph.arriveAndAwaitAdvance(); job.step2Task(); System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "Assemble at the park gate"); ph.arriveAndAwaitAdvance(); job.step3Task(); ph.arriveAndAwaitAdvance(); job.step4Task(); // Done, sign out and leave ph.arriveAndDeregister(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } // Let two employees who don't attend the dinner join for (int i = 0; i < 2; i++) { // Increase the number of participating tasks ph.register(); new Thread(new Runnable() { @Override public void run() { try { job.step1Task(); ph.arriveAndAwaitAdvance(); job.step2Task(); System.out.println( "Staff[" + Thread.currentThread().getName() + "]" + "go back home"); // Done, sign out and leave ph.arriveAndDeregister(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } while (!ph.isTerminated()) { int phaser = ph.arriveAndAwaitAdvance(); if (phaser == 2) { // At the stage of going to the restaurant, let people who only participate in the evening dinner join for (int i = 0; i < 4; i++) { // Increase the number of participating tasks ph.register(); new Thread(new Runnable() { @Override public void run() { try { job.step3Task(); ph.arriveAndAwaitAdvance(); job.step4Task(); // Done, sign out and leave ph.arriveAndDeregister(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } } } } }