DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • The Impact of AI Agents on Modern Workflows
  • A Developer’s Guide to Multithreading and Swift Concurrency
  • Mastering AI Agents: How Agentic Design Patterns Make Agents Smarter
  • Deep Work for Site Reliability Engineers

Trending

  • Stop Building Monolithic AI Brains, Build a Specialist Team Instead
  • Breaking Free from ZooKeeper: Why Kafka’s KRaft Mode Matters
  • The AWS Playbook for Building Future-Ready Data Systems
  • Stop Prompt Hacking: How I Connected My AI Agent to Any API With MCP

Waiting for Tasks With Phaser

Need to wait for other threads? Let's dive into the Phaser class and its assorted methods like arrive and register to see how it can work for you.

By 
Thomas Krieger user avatar
Thomas Krieger
·
Apr. 20, 18 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
9.2K Views

Join the DZone community and get the full member experience.

Join For Free

The class Phaser lets you wait for a flexible number of tasks executed in other threads. Use the method register to add a task you want to wait for. Call arrive to signal that a registered task is finished. And call awaitAdvance to wait until all registered tasks are finished. We will see how to use it by looking at a real-life example. But first, how does it work?

How Does Phaser Work?

The class Phaser works in phases. You register tasks for all phases by calling the method register. You signal that a task is finished for this phase by calling arrive. When all registered tasks have arrived for this phase, the Phaser starts a new phase and you can start over again. The following shows this for the first phase, phase zero:

Phaser phaser = new Phaser();
assertEquals(  0 , phaser.register() );
assertEquals(  0 , phaser.arrive()   );


Both methods return the current phase, phase 0 in the example. By calling arrive, line 3 in the example above, the Phaser starts a new phase 1:

assertEquals(  1 , phaser.getPhase() ); 


And we can start over again, calling arrive to start a new phase:

assertEquals(  1 , phaser.arrive()   );     
assertEquals(  2 , phaser.getPhase() );


The Phaser lets us wait for other threads via the method awaitAdvance. awaitAdvance lets a thread wait until the Phaser reaches a new phase. You call the awaitAdvance method with the current phase to wait for other threads:

phaser.awaitAdvance( phaser.getPhase() );  // waits for phaser.arrive() in other threads


awaitAdvance returns immediately if the current phase is not equal to the given phase value:

phaser.awaitAdvance( phaser.getPhase()  + 1); // returns immediately


Deregistering Tasks and the Terminal State

The Phaser lets you deregister tasks by calling arriveAndDeregister:

phaser.arriveAndDeregister();


When all registered tasks are deregistered the Phaser gets terminated:

assertEquals(  true , phaser.isTerminated() );


When the Phaser is terminated, arrive and register have no effect and return a negative number. And the method await returns immediately. You can change this behavior by overriding the method onAdvance:

Phaser phaser = new Phaser() {
    protected boolean onAdvance(int phase, int parties) { return false; }
}


By always returning false, as in the example above, the Phaser can only be terminated by calling the method forceTermination explicitly.

Example: Waiting for Other Threads

The class ChangedFilesCollector from the IntelliJ community edition uses the Phaser to wait until all threads have reached a specific state. The used Phaser overrides the onAdvance method to allow to reuse the Phaser when all tasks are deregistered:

private final Phaser myWorkersFinishedSync = new Phaser() {
    @Override
    protected boolean onAdvance(int phase, int registeredParties) {
        return false;
    }
};


In the method processFilesInReadAction, this Phaser is used to wait until all threads have finished their tasks:

private void processFilesInReadAction() {
    assert ApplicationManager.getApplication().isReadAccessAllowed();
    myWorkersFinishedSync.register();
    int phase = myWorkersFinishedSync.getPhase();
    try {
        // other statements omitted
    } finally {
        myWorkersFinishedSync.arriveAndDeregister();
    }
    myWorkersFinishedSync.awaitAdvance(phase);
}


In line 3, the method register registers a new task. The variable phase remembers the current phase in line 4. In line 8, the method arriveAndDeregister signals that the task is done and deregisters the task. And in line 10, we wait for the other threads using the method awaitAdvance.

Other Classes to Wait for Threads

Java provides three classes to wait for other threads: Phaser, CountDownLatch, and CyclicBarrier. Use Phaser when you need to wait for a flexible number of threads. When you need to wait for a fixed amount of tasks done in other threads, use CountDownLatch instead. And use CyclicBarrier when you do the work and need to wait in the same threads for a fixed amount of threads.

Next Steps

This was the last java.util.concurrent class to wait for other threads. In the next blog post, we will look at the classes in the package java.util.concurrent.atomic.

I would be glad to hear from you about how you use Phaser in your applications.

Task (computing)

Published at DZone with permission of Thomas Krieger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Impact of AI Agents on Modern Workflows
  • A Developer’s Guide to Multithreading and Swift Concurrency
  • Mastering AI Agents: How Agentic Design Patterns Make Agents Smarter
  • Deep Work for Site Reliability Engineers

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: