Java Gold SE11対策:ExecutorServiceによるスレッド管理

アイキャッチ画像

ExecutorServiceとは?

Javaでスレッドを扱う方法は大きく2種類あります:

  • new Thread(…).start() のように、自分でスレッドを直接作る方法
  • ExecutorService を使って、スレッドを管理してもらう方法 ← 実務ではこちらが主流!

ExecutorService を使うと、スレッドの使い回し(再利用)やシャットダウン処理をしやすくなり、無駄なスレッドの増加を防げるのが特徴です。

基本構文と仕組み

ExecutorService executor = Executors.newSingleThreadExecutor();

executor.submit(() -> {

    System.out.println(“スレッド実行中!”);

});

executor.shutdown();

ここで使っている要素

要素役割
ExecutorServiceスレッド管理のインタフェース
Executorsファクトリクラス(インスタンス生成を担当)
newSingleThreadExecutor()1つのスレッドだけを使う実装(他にも種類あり)
submit()タスクを実行(Runnable や Callable を渡せる)
shutdown()処理完了後にスレッドを終了させる命令

スレッドプールを使うパターン

複数スレッドを同時に使いたいときは、FixedThreadPool を使うのが基本です。

ExecutorService executor = Executors.newFixedThreadPool(3);

for (int i = 1; i <= 5; i++) {

    final int taskId = i;

    executor.submit(() -> {

        System.out.println(“Task ” + taskId + ” 開始”);

        try {

            Thread.sleep(1000); // 疑似的な処理

        } catch (InterruptedException e) {

            Thread.currentThread().interrupt();

        }

        System.out.println(“Task ” + taskId + ” 終了”);

    });

}

executor.shutdown();

処理の流れ(例)

  • スレッド数は3つ固定
  • タスクは5つ送る
  • 最初の3つのタスクはすぐ実行される
  • 残り2つは、前のタスクが終わるまで 待機
  • 終わったスレッドから順に次のタスクを実行

スレッドプールの種類(Executorsの主なメソッド)

メソッド名特徴
newSingleThreadExecutor()常に1つだけのスレッド
newFixedThreadPool(int n)n個のスレッドで処理
newCachedThreadPool()必要なだけスレッド生成し、使い終わったら再利用
newScheduledThreadPool(int n)定期実行や遅延実行が可能

submit() と execute() の違い

メソッド特徴
execute(Runnable task)戻り値なし、例外キャッチ不可
submit(Callable / Runnable task)戻り値(Future)あり、例外を取得可能

🔚 終了処理を忘れずに!

executor.shutdown(); // 正常終了(受け付け停止)

executor.shutdownNow(); // 強制終了(実行中も止める)

// 最大5秒待って、それでも終わらなければ強制終了!

if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {

    executor.shutdownNow();

}

shutdown() を忘れると、アプリが終了しないバグになることも!

まとめ

用語意味・役割
ExecutorServiceスレッドを効率よく管理するインタフェース
Executorsスレッドプールを作るファクトリクラス
FixedThreadPool複数スレッドを再利用して効率的に処理
shutdown()スレッドプールを終了(必ず書く!)