Registration. Unlike the case for other barriers, the
number of parties registered to synchronize on a phaser
may vary over time. Tasks may be registered at any time (using
bulkRegister(int), or forms of
constructors establishing initial numbers of parties), and
optionally deregistered upon any arrival (using
arriveAndDeregister()). As is the case with most basic
synchronization constructs, registration and deregistration affect
only internal counts; they do not establish any further internal
bookkeeping, so tasks cannot query whether they are registered.
(However, you can introduce such bookkeeping by subclassing this
Synchronization. Like a
Phaser may be repeatedly awaited. Method
arriveAndAwaitAdvance() has effect analogous to
generation of a phaser has an associated phase number. The phase
number starts at zero, and advances when all parties arrive at the
phaser, wrapping around to zero after reaching
Integer.MAX_VALUE. The use of phase numbers enables independent
control of actions upon arrival at a phaser and upon awaiting
others, via two kinds of methods that may be invoked by any
- Arrival. Methods
arriveAndDeregister()record arrival. These methods do not block, but return an associated arrival phase number; that is, the phase number of the phaser to which the arrival applied. When the final party for a given phase arrives, an optional action is performed and the phase advances. These actions are performed by the party triggering a phase advance, and are arranged by overriding method
onAdvance(int, int), which also controls termination. Overriding this method is similar to, but more flexible than, providing a barrier action to a
- Waiting. Method
awaitAdvance(int)requires an argument indicating an arrival phase number, and returns when the phaser advances to (or is already at) a different phase. Unlike similar constructions using
awaitAdvancecontinues to wait even if the waiting thread is interrupted. Interruptible and timeout versions are also available, but exceptions encountered while tasks wait interruptibly or with timeout do not change the state of the phaser. If necessary, you can perform any associated recovery within handlers of those exceptions, often after invoking
forceTermination. Phasers may also be used by tasks executing in a
ForkJoinPool. Progress is ensured if the pool's parallelismLevel can accommodate the maximum number of simultaneously blocked parties.
Termination. A phaser may enter a termination
state, that may be checked using method
termination, all synchronization methods immediately return without
waiting for advance, as indicated by a negative return value.
Similarly, attempts to register upon termination have no effect.
Termination is triggered when an invocation of
true. The default implementation returns
true if a deregistration has caused the number of registered
parties to become zero. As illustrated below, when phasers control
actions with a fixed number of iterations, it is often convenient
to override this method to cause termination when the current phase
number reaches a threshold. Method
also available to abruptly release waiting threads and allow them
Tiering. Phasers may be tiered (i.e., constructed in tree structures) to reduce contention. Phasers with large numbers of parties that would otherwise experience heavy synchronization contention costs may instead be set up so that groups of sub-phasers share a common parent. This may greatly increase throughput even though it incurs greater per-operation overhead.
In a tree of tiered phasers, registration and deregistration of
child phasers with their parent are managed automatically.
Whenever the number of registered parties of a child phaser becomes
non-zero (as established in the
child phaser is registered with its parent. Whenever the number of
registered parties becomes zero as the result of an invocation of
arriveAndDeregister(), the child phaser is deregistered
from its parent.
Monitoring. While synchronization methods may be invoked
only by registered parties, the current state of a phaser may be
monitored by any caller. At any given moment there are
getRegisteredParties() parties in total, of which