CountDownLatchによるスレッド間の同期制御

複数の非同期タスクがすべて終了した後で次の処理を開始したい場合、CountDownLatchを使うと簡潔に記述できる。内部的には「残りタスク数」を管理するカウンタを持ち、各タスクは完了時にcountDown()でカウンタをデクリメントし、待機側はawait()でカウンタがゼロになるまでブロックされる。

主要APIの概要

コンストラクタ

CountDownLatch latch = new CountDownLatch(並行タスク数);

頻出メソッド

  • await() : 現在のスレッドを、カウンタが0になるまで中断
  • await(long, TimeUnit) : タイムアウト付き待機。時間切れでfalseを返却
  • countDown() : カウンタを1減算し、0になった時点で待機スレッドを起床

実践例:撮影・認証後にアップロードを実行

以下のコードでは、撮影スレッドと認証スレッドが終了してから、サーバへのアップロードスレッドを起動する。

import java.util.concurrent.CountDownLatch;

public class UploadAfterTasks {
    public static void main(String[] args) throws InterruptedException {
        final int TASKS = 2;
        CountDownLatch gate = new CountDownLatch(TASKS);

        Thread photo = new Thread(() -> {
            try {
                Thread.sleep(1500);
                System.out.println("撮影完了");
            } catch (InterruptedException ignored) {
            } finally {
                gate.countDown();
            }
        });

        Thread auth = new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("認証完了");
            } catch (InterruptedException ignored) {
            } finally {
                gate.countDown();
            }
        });

        Thread upload = new Thread(() -> {
            try {
                gate.await();
                System.out.println("サーバへアップロード開始");
            } catch (InterruptedException ignored) {
            }
        });

        photo.start();
        auth.start();
        upload.start();
    }
}

実行結果の一例

認証完了
撮影完了
サーバへアップロード開始

タグ: CountDownLatch Java並行処理 スレッド同期 AQS

6月16日 19:15 投稿