jakson
jakson

Reputation: 343

Using and reusing Phaser instead of join()

I have to wait in main thread for termination of working threads, then (on some event) I start those threads and wait for termination again, etc.

Calling join() works well, but I want to do it faster.

Phaser looks like what I'm searching for, but I'm doing something wrong:

//*** application start ***
//create "empty" Phaser

//*** main thread ***
//event occured - start working threads
phaser.register();
//start working threads...
phaser.arriveAndAwaitAdvance(); //add arriveAndDeregister()?

// *** working thread start ***
phaser.register();
// do sth ...
// *** working thread end ***
phaser.arrive(); // replace with arriveAndDeregister()?

Upvotes: 1

Views: 597

Answers (1)

Tiago Cogumbreiro
Tiago Cogumbreiro

Reputation: 549

The problem is that you are cannot call phaser.register() from within the task being registered. When using phasers always follow these two rules:

  1. Only registered tasks can register other tasks. This means that a task cannot register itself.
  2. All registered tasks must deregister before ending. A good practice is to wrap the code using a phaser around a finally block that deregisters at the end (see example).

Here is how you would change your original example:

//*** application start ***
//create "empty" Phaser
final Phaser phaser = new Phaser(1);
//*** main thread ***
//event occurred - start working threads
for (int i = 0; i < WORKERS; i++) { // spawn some workers
  phaser.register(); // register the worker thread before starting it
  Thread worker = new Thread(new Runnable() {
    @Override
      public void run() {
        try { // wrap the worker's code with a finally, so you are sure the task will deregister from the phaser.
          // Worker's code
          // ...
          // *** working thread end ***
          // last operation is:
        } finally { // Very important to wrap
          phaser.arriveAndDeregister();
        }
      }
  });
  worker.start();
}
// wait for working threads...
phaser.arriveAndAwaitAdvance();

// repeat pattern above: phaser.register() + worker.start()
phaser.arriveAndAwaitAdvance();

// since the main task is done it deregisters itself from the phaser
phaser.arriveAndDeregister();

Upvotes: 1

Related Questions