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() | スレッドプールを終了(必ず書く!) |