1. 導入:なぜCyclicBarrierが必要なのか?
並行処理において、複数のスレッドで重い処理を並列実行し、すべての処理が終わったタイミングで「次のステップ」へ進みたいというケースはよくあります。例えば、ゲームのロード画面で「プレイヤー情報」「マップデータ」「テクスチャ」を個別に読み込み、すべて完了した後にゲームを開始するような状況です。これを実現するための強力なツールが、java.util.concurrent.CyclicBarrierです。
2. 基礎知識:CyclicBarrierとは?
CyclicBarrierは、指定した数のスレッドが特定の地点(バリアポイント)に到達するまで、それらのスレッドを待機させるための同期用クラスです。「Cyclic(循環的)」という名の通り、バリアが解除された後に再度利用できるのが特徴です。
主な用語:
・パーティ数(parties):待機させるスレッドの数。
・バリアアクション(barrier action):すべてのスレッドが到達した瞬間に一度だけ実行されるタスク。
3. 実装/解決策
CyclicBarrierを利用するには、まず「待機させたいスレッド数」を指定してインスタンスを生成します。各スレッド内でawait()メソッドを呼び出すことで、指定数に達するまで処理がブロックされます。
4. サンプルプログラム
以下のコードは、3つのスレッドが処理を完了した時点で、メイン処理が実行される例です。
import java.util.concurrent.CyclicBarrier;
public class BarrierExample {
public static void main(String[] args) {
int numberOfThreads = 3;
// 全スレッドが到達した後に実行されるアクション
Runnable barrierAction = () -> System.out.println("★全員集合!次のステージへ進みます。");
// 3つのスレッドを待機させるバリアを生成
CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, barrierAction);
for (int i = 1; i <= numberOfThreads; i++) {
new Thread(new Worker(barrier, i)).start();
}
}
}
class Worker implements Runnable {
private CyclicBarrier barrier;
private int id;
public Worker(CyclicBarrier barrier, int id) {
this.barrier = barrier;
this.id = id;
}
public void run() {
try {
System.out.println("スレッド " + id + " が処理を開始します...");
Thread.sleep((long) (Math.random() 3000)); // 処理時間をシミュレート
System.out.println("スレッド " + id + " がバリア地点に到達しました。");
// ここで待機。指定数に達するまで処理が止まる
barrier.await();
System.out.println("スレッド " + id + " が再開しました!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
5. 応用・注意点:現場で陥りやすい罠
現場で活用する際には、以下の点に注意してください。
・例外処理:await()メソッドは、InterruptedExceptionやBrokenBarrierExceptionをスローします。バリアが壊れた場合(他のスレッドが中断された場合など)、すべてが停止してしまうため、適切なエラーハンドリングが必要です。
・タイムアウトの検討:await(long timeout, TimeUnit unit)を使うと、指定時間内に全員が揃わない場合に例外を投げることができます。無限に待機し続けるデッドロックを防ぐため、実務ではタイムアウト付きの利用を推奨します。
・最新技術との併用:Java 21以降のVirtual Threads環境でもCyclicBarrierは動作しますが、複雑な非同期処理を行う場合は、より柔軟なCompletableFutureのallOf()や、構造化並行処理(Structured Concurrency)の利用も検討しましょう。
CyclicBarrierは、複数の処理の「足並みを揃える」ための非常に直感的な手段です。まずはこのサンプルを動かして、スレッドの動きを体感してみてください。

コメント