Phaser クラス
定義
重要
一部の情報は、リリース前に大きく変更される可能性があるプレリリースされた製品に関するものです。 Microsoft は、ここに記載されている情報について、明示または黙示を問わず、一切保証しません。
再利用可能な同期バリア。機能が CyclicBarrier や CountDownLatch に似ていますが、より柔軟な使用をサポートします。
[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
- 継承
- 属性
注釈
再利用可能な同期バリア。機能が CyclicBarrier や CountDownLatch に似ていますが、より柔軟な使用をサポートします。
<b>Registration.</b> 他のバリアの場合とは異なり、フェイザーで同期する<>登録</em>の数は、時間の経過と伴って異なる場合があります。 タスクはいつでも登録できます (メソッド #register、 #bulkRegister、またはフォームのコンストラクターを使用してパーティーの初期数を確立し、必要に応じて任意の到着時に登録を解除 ( #arriveAndDeregisterを使用)。 ほとんどの基本的な同期コンストラクトの場合と同様に、登録と登録解除は内部カウントにのみ影響します。それ以上の内部ブックキーピングは確立されないため、タスクは登録されているかどうかを照会できません。 (ただし、このクラスをサブクラス化することで、このようなブックキーピングを導入できます。
<b>Synchronization.</b>CyclicBarrierと同様に、 Phaser を繰り返し待機できます。 メソッド #arriveAndAwaitAdvance は、 java.util.concurrent.CyclicBarrier#await CyclicBarrier.awaitに似た効果があります。 フェイザーの各生成には、関連するフェーズ番号があります。 フェーズ番号はゼロから始まり、すべての当事者がフェイザーに到着すると進み、 Integer.MAX_VALUEに達した後にゼロに折り返されます。 フェーズ番号を使用すると、任意の登録済みパーティによって呼び出される可能性のある 2 種類のメソッドを使用して、フェイザーに到着した場合と他のユーザーを待機するときのアクションを独立して制御できます。
<ul>
<li><b>Arrival.</b> レコード到着の #arrive と #arriveAndDeregister メソッド。 これらのメソッドはブロックしませんが、関連付けられた <em>arrival フェーズ番号</em>; を返します。つまり、到着が適用されたフェイザーのフェーズ番号です。 特定のフェーズの最終パーティが到着すると、オプションのアクションが実行され、フェーズが進みます。 これらのアクションは、フェーズの進行をトリガーするパーティによって実行され、終了も制御するメソッド #onAdvance(int, int)をオーバーライドすることによって配置されます。 このメソッドのオーバーライドは、 CyclicBarrierにバリア アクションを提供する方法と似ていますが、より柔軟です。
<li><b>Waiting.</b> メソッド #awaitAdvance には、到着フェーズ番号を示す引数が必要であり、フェイザーが別のフェーズに進む (または既にある) ときに戻ります。
CyclicBarrierを使用した同様の構造とは異なり、メソッドawaitAdvanceは待機中のスレッドが中断された場合でも待機を続けます。 割り込み可能なバージョンとタイムアウト バージョンも使用できますが、タスクが中断的に待機中またはタイムアウト時に発生した例外は、フェイザーの状態を変更しません。 必要に応じて、多くの場合、 forceTerminationを呼び出した後、これらの例外のハンドラー内で関連する回復を実行できます。 フェイザーは、 ForkJoinPoolで実行されるタスクでも使用できます。 プールの並列処理レベルが同時にブロックされるパーティの最大数に対応できる場合は、進行状況が保証されます。
</ul>
<b>Termination.</b> フェイザーは <em>termination</em> 状態に入り、メソッド #isTerminatedを使用してチェックできます。 終了すると、すべての同期メソッドは、負の戻り値で示されているように、事前に待機せずに直ちに戻ります。 同様に、終了時に登録を試みると影響はありません。 終了は、 onAdvance の呼び出しが trueを返すとトリガーされます。 既定の実装では、登録解除によって登録されたパーティの数が 0 になった場合、 true が返されます。 次に示すように、フェイザーが固定回数の反復でアクションを制御する場合、現在のフェーズ番号がしきい値に達したときに終了を発生させるために、このメソッドをオーバーライドすると便利です。 メソッド #forceTermination は、待機中のスレッドを突然解放して終了できるようにすることもできます。
<b>Tiering.</b> Phasers を <em>tiered</em> (ツリー構造で構築) して競合を減らすことができます。 それ以外の場合に高い同期競合コストが発生するパーティの数が多いフェイザーは、代わりにサブフェーズのグループが共通の親を共有するように設定できます。 これにより、操作ごとのオーバーヘッドが大きくなる場合でも、スループットが大幅に向上する可能性があります。
階層化されたフェイザーのツリーでは、親を持つ子フェイザーの登録と登録解除が自動的に管理されます。 子フェイザーの登録済みパーティの数が 0 以外になると ( #Phaser(Phaser,int) コンストラクター、 #register、または #bulkRegisterで確立された場合)、子フェイザーはその親に登録されます。
#arriveAndDeregisterの呼び出しの結果、登録されたパーティの数が 0 になると、子フェイザーは親から登録解除されます。
<b>Monitoring.</b> 同期メソッドは登録済みパーティのみが呼び出すことができますが、フェイザーの現在の状態は任意の呼び出し元によって監視できます。 現在のフェーズ (#getRegisteredParties) に到着した#getArrivedParties、任意の時点で、合計で#getPhaseパーティがあります。 残りの (#getUnarrivedParties) パーティーが到着すると、フェーズが進みます。 これらのメソッドによって返される値は一時的な状態を反映している可能性があるため、一般的に同期制御には役立ちません。 メソッド #toString は、非公式の監視に便利な形式で、これらの状態クエリのスナップショットを返します。
メモリ整合性の影響: 任意の形式の arrive メソッドの前のアクション <i>happen-before</i> 対応するフェーズの進めアクションと onAdvance アクション (存在する場合)、フェーズの進行に続く アクションが発生 します。
<b>Sample usages:</b>
Phaserは、CountDownLatchの代わりに使用して、可変の数のパーティにサービスを提供するワンショット アクションを制御できます。 一般的なイディオムは、最初に登録し、次にすべてのアクションを開始してから登録を解除するように設定するメソッドです。
{@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();
}}
一連のスレッドで特定の反復回数に対してアクションを繰り返し実行する 1 つの方法は、 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();
}}
メイン タスクが後で終了を待機する必要がある場合は、再登録してから、同様のループを実行できます。
{@code
// ...
phaser.register();
while (!phaser.isTerminated())
phaser.arriveAndAwaitAdvance();}
関連する構造を使用して、フェーズが Integer.MAX_VALUE周りに折り返されないことが確実なコンテキストで特定のフェーズ番号を待機できます。 例えば次が挙げられます。
{@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();
}}
フェーズのツリーを使用して一連の n タスクを作成するには、構築時に登録する Phaser を受け入れるコンストラクターを持つ Task クラスを想定して、次の形式のコードを使用できます。
build(new Task[n], 0, n, new Phaser())の呼び出し後、プールに送信するなどして、これらのタスクを開始できます。
{@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()
}
}}
TASKS_PER_PHASERの最適な値は、主に予想される同期率によって異なります。 4 個までの値は、非常に小さなフェーズ単位のタスク本体 (したがって高いレート) に適しているか、非常に大きいタスクの場合は最大数百に適しています。
<b>実装に関する注意事項:</b> この実装では、パーティの最大数が 65535 に制限されます。 追加のパーティを登録しようとすると、 IllegalStateExceptionが発生します。 ただし、任意に大規模な参加者のセットに対応するために、階層化されたフェイザーを作成できます。また、階層化されたフェイザーを作成する必要があります。
1.7 で追加されました。
このページの一部は、によって作成および共有され、に記載されている条件に従って使用される作業に基づく変更です。
コンストラクター
| 名前 | 説明 |
|---|---|
| Phaser() |
最初に登録されたパーティ、親、および初期フェーズ番号 0 を持たない新しいフェイザーを作成します。 |
| Phaser(Int32) |
指定された数の登録済みパーティ (親なし)、初期フェーズ番号 0 を使用して、新しいフェイザーを作成します。 |
| Phaser(IntPtr, JniHandleOwnership) |
JNI オブジェクトのマネージド表現を作成するときに使用されるコンストラクター。ランタイムによって呼び出されます。 |
| Phaser(Phaser, Int32) |
指定された親と登録されていないパーティの数を持つ新しいフェイザーを作成します。 |
| Phaser(Phaser) |
|
プロパティ
| 名前 | 説明 |
|---|---|
| ArrivedParties |
このフェイザーの現在のフェーズに到着した登録済みパーティの数を返します。 |
| Class |
この |
| Handle |
基になる Android インスタンスへのハンドル。 (継承元 Object) |
| IsTerminated |
このフェイザーが終了した場合に |
| JniIdentityHashCode |
相互運用ランタイムによってこのJava ピアに割り当てられた ID ハッシュ コードを取得します。 (継承元 Object) |
| JniManagedPeerState |
再利用可能な同期バリア。機能が |
| JniPeerMembers |
再利用可能な同期バリア。機能が |
| Parent |
このフェイザーの親を返します。存在しない場合は |
| PeerReference |
このJava ピアの JNI オブジェクト参照を取得します。 (継承元 Object) |
| Phase |
現在のフェーズ番号を返します。 |
| RegisteredParties |
このフェイザーで登録されたパーティの数を返します。 |
| Root |
このフェイザーのルート先祖を返します。親がない場合は、このフェイザーと同じです。 |
| ThresholdClass |
この API は Android 用 Mono インフラストラクチャをサポートしており、コードから直接使用するためのものではありません。 |
| ThresholdType |
この API は Android 用 Mono インフラストラクチャをサポートしており、コードから直接使用するためのものではありません。 |
| UnarrivedParties |
このフェイザーの現在のフェーズにまだ到着していない登録済みパーティの数を返します。 |
メソッド
| 名前 | 説明 |
|---|---|
| Arrive() |
他のユーザーが到着するのを待たずに、このフェイザーに到着します。 |
| ArriveAndAwaitAdvance() |
このフェイザーに到着し、他の人を待ちます。 |
| ArriveAndDeregister() |
このフェイザーに到着し、他のユーザーが到着するのを待たずに、そこから登録を解除します。 |
| AwaitAdvance(Int32) |
現在のフェーズが指定されたフェーズ値と等しくないか、このフェイザーが終了した場合に直ちに戻り、指定されたフェーズ値から進むまで、このフェイザーのフェーズを待機します。 |
| AwaitAdvanceInterruptibly(Int32, Int64, TimeUnit) |
このフェイザーのフェーズが、指定されたフェーズ値または指定されたタイムアウトから経過するまで待機するか、待機中に中断された場合は |
| AwaitAdvanceInterruptibly(Int32) |
このフェイザーのフェーズが指定されたフェーズ値から進むのを待ち、待機中に中断された場合は |
| BulkRegister(Int32) |
指定された数の新しい未接続のパーティをこのフェイザーに追加します。 |
| Clone() |
このオブジェクトのコピーを作成して返します。 (継承元 Object) |
| Construct(JniObjectReference, JniObjectReferenceOptions) |
再利用可能な同期バリア。機能が |
| Dispose() |
このJava ピアによって保持されているリソースを解放します。 (継承元 Object) |
| Dispose(Boolean) |
このJava ピアによって保持されているリソースを解放します。 (継承元 Object) |
| DisposeUnlessReferenced() |
再利用可能な同期バリア。機能が |
| Equals(Object) |
再利用可能な同期バリア。機能が |
| Equals(Object) |
他のオブジェクトがこのオブジェクトと "等しい" かどうかを示します。 (継承元 Object) |
| ForceTermination() |
このフェイザーが強制終了状態になります。 |
| GetHashCode() |
オブジェクトのハッシュ コード値を返します。 (継承元 Object) |
| JavaFinalize() |
古い.
オブジェクトへの参照がなくなったとガベージ コレクションによって判断されたときに、オブジェクトのガベージ コレクターによって呼び出されます。 (継承元 Object) |
| Notify() |
このオブジェクトのモニターで待機している 1 つのスレッドを起動します。 (継承元 Object) |
| NotifyAll() |
このオブジェクトのモニターで待機しているすべてのスレッドを起動します。 (継承元 Object) |
| OnAdvance(Int32, Int32) |
フェーズの進行が迫った場合にアクションを実行し、終了を制御するオーバーライド可能なメソッド。 |
| Register() |
このフェイザーに新しい未接続のパーティーを追加します。 |
| SetHandle(IntPtr, JniHandleOwnership) |
Handle プロパティを設定します。 (継承元 Object) |
| SetPeerReference(JniObjectReference, JniObjectReferenceOptions) |
再利用可能な同期バリア。機能が |
| ToArray<T>() |
このJava配列ラッパーからマネージド配列を作成します。 (継承元 Object) |
| ToString() |
オブジェクトの文字列表現を返します。 (継承元 Object) |
| UnregisterFromRuntime() |
相互運用ランタイムからこのJava ピアの登録を解除します。 (継承元 Object) |
| Wait() |
現在のスレッドが起動するまで待機します。通常は、 <em>notified</em> または <em>interrupted</em>。 (継承元 Object) |
| Wait(Int64, Int32) |
現在のスレッドは、通常、 <em>notified</em> または <em>interrupted</em>、または一定のリアルタイムが経過するまで、起動されるまで待機します。 (継承元 Object) |
| Wait(Int64) |
現在のスレッドは、通常、 <em>notified</em> または <em>interrupted</em>、または一定のリアルタイムが経過するまで、起動されるまで待機します。 (継承元 Object) |
明示的なインターフェイスの実装
| 名前 | 説明 |
|---|---|
| IJavaPeerable.Disposed() |
再利用可能な同期バリア。機能が |
| IJavaPeerable.Finalized() |
再利用可能な同期バリア。機能が |
| IJavaPeerable.JniObjectReferenceControlBlock |
再利用可能な同期バリア。機能が |
| IJavaPeerable.SetJniIdentityHashCode(Int32) |
再利用可能な同期バリア。機能が |
| IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) |
再利用可能な同期バリア。機能が |
| IJavaPeerable.SetPeerReference(JniObjectReference) |
再利用可能な同期バリア。機能が |
拡張メソッド
| 名前 | 説明 |
|---|---|
| GetJniTypeName(IJavaPeerable) |
インスタンス |
| JavaAs<TResult>(IJavaPeerable) |
|
| JavaCast<TResult>(IJavaObject) |
Android ランタイムチェック型変換を実行します。 |
| JavaCast<TResult>(IJavaObject) |
再利用可能な同期バリア。機能が |
| TryJavaCast<TResult>(IJavaPeerable, TResult) |
|