Sdílet prostřednictvím


Phaser Class

Definition

A reusable synchronization barrier, similar in functionality to CyclicBarrier and CountDownLatch but supporting more flexible usage.

[Android.Runtime.Register("java/util/concurrent/Phaser", DoNotGenerateAcw=true)]
public class Phaser : Java.Lang.Object
[<Android.Runtime.Register("java/util/concurrent/Phaser", DoNotGenerateAcw=true)>]
type Phaser = class
    inherit Object
Inheritance
Phaser
Attributes

Remarks

A reusable synchronization barrier, similar in functionality to CyclicBarrier and CountDownLatch but supporting more flexible usage.

<b>Registration.</b> Unlike the case for other barriers, the number of parties <em>registered</em> to synchronize on a phaser may vary over time. Tasks may be registered at any time (using methods #register, #bulkRegister, 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 class.)

<b>Synchronization.</b> Like a CyclicBarrier, a Phaser may be repeatedly awaited. Method #arriveAndAwaitAdvance has effect analogous to java.util.concurrent.CyclicBarrier#await CyclicBarrier.await. Each 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 registered party:

<ul>

<li><b>Arrival.</b> Methods #arrive and #arriveAndDeregister record arrival. These methods do not block, but return an associated <em>arrival phase number</em>; 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 CyclicBarrier.

<li><b>Waiting.</b> Method #awaitAdvance 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 CyclicBarrier, method awaitAdvance continues 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 parallelism level can accommodate the maximum number of simultaneously blocked parties.

</ul>

<b>Termination.</b> A phaser may enter a <em>termination</em> state, that may be checked using method #isTerminated. Upon 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 onAdvance returns 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 #forceTermination is also available to abruptly release waiting threads and allow them to terminate.

<b>Tiering.</b> Phasers may be <em>tiered</em> (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 #Phaser(Phaser,int) constructor, #register, or #bulkRegister), 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.

<b>Monitoring.</b> 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 #getArrivedParties have arrived at the current phase (#getPhase). When the remaining (#getUnarrivedParties) parties arrive, the phase advances. The values returned by these methods may reflect transient states and so are not in general useful for synchronization control. Method #toString returns snapshots of these state queries in a form convenient for informal monitoring.

Memory consistency effects: Actions prior to any form of arrive method <i>happen-before</i> a corresponding phase advance and onAdvance actions (if present), which in turn happen-before actions following the phase advance.

<b>Sample usages:</b>

A Phaser may be used instead of a CountDownLatch to control a one-shot action serving a variable number of parties. The typical idiom is for the method setting this up to first register, then start all the actions, then deregister, as in:

{@code
            void runTasks(List<Runnable> tasks) {
              Phaser startingGate = new Phaser(1); // "1" to register self
              // create and start threads
              for (Runnable task : tasks) {
                startingGate.register();
                new Thread(() -> {
                  startingGate.arriveAndAwaitAdvance();
                  task.run();
                }).start();
              }

              // deregister self to allow threads to proceed
              startingGate.arriveAndDeregister();
            }}

One way to cause a set of threads to repeatedly perform actions for a given number of iterations is to override onAdvance:

{@code
            void startTasks(List<Runnable> tasks, int iterations) {
              Phaser phaser = new Phaser() {
                protected boolean onAdvance(int phase, int registeredParties) {
                  return phase >= iterations - 1 || registeredParties == 0;
                }
              };
              phaser.register();
              for (Runnable task : tasks) {
                phaser.register();
                new Thread(() -> {
                  do {
                    task.run();
                    phaser.arriveAndAwaitAdvance();
                  } while (!phaser.isTerminated());
                }).start();
              }
              // allow threads to proceed; don't wait for them
              phaser.arriveAndDeregister();
            }}

If the main task must later await termination, it may re-register and then execute a similar loop:

{@code
              // ...
              phaser.register();
              while (!phaser.isTerminated())
                phaser.arriveAndAwaitAdvance();}

Related constructions may be used to await particular phase numbers in contexts where you are sure that the phase will never wrap around Integer.MAX_VALUE. For example:

{@code
            void awaitPhase(Phaser phaser, int phase) {
              int p = phaser.register(); // assumes caller not already registered
              while (p < phase) {
                if (phaser.isTerminated())
                  // ... deal with unexpected termination
                else
                  p = phaser.arriveAndAwaitAdvance();
              }
              phaser.arriveAndDeregister();
            }}

To create a set of n tasks using a tree of phasers, you could use code of the following form, assuming a Task class with a constructor accepting a Phaser that it registers with upon construction. After invocation of build(new Task[n], 0, n, new Phaser()), these tasks could then be started, for example by submitting to a pool:

{@code
            void build(Task[] tasks, int lo, int hi, Phaser ph) {
              if (hi - lo > TASKS_PER_PHASER) {
                for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
                  int j = Math.min(i + TASKS_PER_PHASER, hi);
                  build(tasks, i, j, new Phaser(ph));
                }
              } else {
                for (int i = lo; i < hi; ++i)
                  tasks[i] = new Task(ph);
                  // assumes new Task(ph) performs ph.register()
              }
            }}

The best value of TASKS_PER_PHASER depends mainly on expected synchronization rates. A value as low as four may be appropriate for extremely small per-phase task bodies (thus high rates), or up to hundreds for extremely large ones.

<b>Implementation notes:</b> This implementation restricts the maximum number of parties to 65535. Attempts to register additional parties result in IllegalStateException. However, you can and should create tiered phasers to accommodate arbitrarily large sets of participants.

Added in 1.7.

Java documentation for java.util.concurrent.Phaser.

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

Constructors

Phaser()

Creates a new phaser with no initially registered parties, no parent, and initial phase number 0.

Phaser(Int32)

Creates a new phaser with the given number of registered unarrived parties, no parent, and initial phase number 0.

Phaser(IntPtr, JniHandleOwnership)

A constructor used when creating managed representations of JNI objects; called by the runtime.

Phaser(Phaser, Int32)

Creates a new phaser with the given parent and number of registered unarrived parties.

Phaser(Phaser)

Equivalent to #Phaser(Phaser, int) Phaser(parent, 0).

Properties

ArrivedParties

Returns the number of registered parties that have arrived at the current phase of this phaser.

Class

Returns the runtime class of this Object.

(Inherited from Object)
Handle

The handle to the underlying Android instance.

(Inherited from Object)
IsTerminated

Returns true if this phaser has been terminated.

JniIdentityHashCode (Inherited from Object)
JniPeerMembers
Parent

Returns the parent of this phaser, or null if none.

PeerReference (Inherited from Object)
Phase

Returns the current phase number.

RegisteredParties

Returns the number of parties registered at this phaser.

Root

Returns the root ancestor of this phaser, which is the same as this phaser if it has no parent.

ThresholdClass

This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.

ThresholdType

This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.

UnarrivedParties

Returns the number of registered parties that have not yet arrived at the current phase of this phaser.

Methods

Arrive()

Arrives at this phaser, without waiting for others to arrive.

ArriveAndAwaitAdvance()

Arrives at this phaser and awaits others.

ArriveAndDeregister()

Arrives at this phaser and deregisters from it without waiting for others to arrive.

AwaitAdvance(Int32)

Awaits the phase of this phaser to advance from the given phase value, returning immediately if the current phase is not equal to the given phase value or this phaser is terminated.

AwaitAdvanceInterruptibly(Int32, Int64, TimeUnit)

Awaits the phase of this phaser to advance from the given phase value or the given timeout to elapse, throwing InterruptedException if interrupted while waiting, or returning immediately if the current phase is not equal to the given phase value or this phaser is terminated.

AwaitAdvanceInterruptibly(Int32)

Awaits the phase of this phaser to advance from the given phase value, throwing InterruptedException if interrupted while waiting, or returning immediately if the current phase is not equal to the given phase value or this phaser is terminated.

BulkRegister(Int32)

Adds the given number of new unarrived parties to this phaser.

Clone()

Creates and returns a copy of this object.

(Inherited from Object)
Dispose() (Inherited from Object)
Dispose(Boolean) (Inherited from Object)
Equals(Object)

Indicates whether some other object is "equal to" this one.

(Inherited from Object)
ForceTermination()

Forces this phaser to enter termination state.

GetHashCode()

Returns a hash code value for the object.

(Inherited from Object)
JavaFinalize()

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.

(Inherited from Object)
Notify()

Wakes up a single thread that is waiting on this object's monitor.

(Inherited from Object)
NotifyAll()

Wakes up all threads that are waiting on this object's monitor.

(Inherited from Object)
OnAdvance(Int32, Int32)

Overridable method to perform an action upon impending phase advance, and to control termination.

Register()

Adds a new unarrived party to this phaser.

SetHandle(IntPtr, JniHandleOwnership)

Sets the Handle property.

(Inherited from Object)
ToArray<T>() (Inherited from Object)
ToString()

Returns a string representation of the object.

(Inherited from Object)
UnregisterFromRuntime() (Inherited from Object)
Wait()

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>.

(Inherited from Object)
Wait(Int64, Int32)

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed.

(Inherited from Object)
Wait(Int64)

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed.

(Inherited from Object)

Explicit Interface Implementations

IJavaPeerable.Disposed() (Inherited from Object)
IJavaPeerable.DisposeUnlessReferenced() (Inherited from Object)
IJavaPeerable.Finalized() (Inherited from Object)
IJavaPeerable.JniManagedPeerState (Inherited from Object)
IJavaPeerable.SetJniIdentityHashCode(Int32) (Inherited from Object)
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) (Inherited from Object)
IJavaPeerable.SetPeerReference(JniObjectReference) (Inherited from Object)

Extension Methods

JavaCast<TResult>(IJavaObject)

Performs an Android runtime-checked type conversion.

JavaCast<TResult>(IJavaObject)
GetJniTypeName(IJavaPeerable)

Applies to