🐶

Java:「スレッドプール」と「ExecutorService」

に公開
2025/11/04

プロローグ

こんにちは、2回目の投稿です。
念のため前置きですが、この記事は、私が本やネットで勉強して自分なりに言葉にしたものです。自分の備忘録みたいなものです。 なので内容に関して誤りもあるかもしれませんが、あしからずご了承くださいませ。 またこの記事の内容に誤りがあればご指摘ください、勉強になります。

テーマ

この記事では
1. スレッドプール技法
2. ExecutorServiceインターフェース
について記載しています。

「スレッドプール」 とは

毎回スレッドを生成せず、あるものを使いまわす技法のことを、「スレッドプール技法」

この技法を用いることで、

  • プラットフォームスレッドの場合、生成時間が実行性能に影響をあたえるので有効。
  • 仮想スレッドの場合、生成と破棄が軽量であり、スレッドプールを利用する利点はそこまでない。

仮想スレッドの場合、ネガティブな意見となってはいるが、ExecutorServiceオブジェクトを利用することで「コードの複雑さの軽減」が見込まれることから推奨できる。

「ExecutorService」インターフェース とは

実際にExecutorServiceを使用した例が以下になります。

ThreadFactory factory = Thread.ofPlatform().factory();
//スレッドプール作成
ExecutorService executor = Executors.newFixedThreadPool(32, factory);
Future<?> result = executor.submit(() -> {
    IntStream.rangeClosed(0, 10)
             .reduce((int acc, int cur) -> acc + cur)
             .ifPresent(System.out::println);
});
//ここでは直下に記載しているが、finallyの中に記載したりする
executor.shutdown();
//10秒だけ待ってあげるね みたいな 処理
executor.awaitTermination(10, TimeUnit.SECONDS);

ここで押さえておくべき処理として、

  • newFixedThreadPool(32, factory);
  • shutdown();
  • awaitTermination(10, TimeUnit.SECONDS);
  • submit()

この4つのメソッドについて取り上げる

使用される クラスメソッドについて

上で記載した4つのメソッドについて

1. Executor newFixedThreadPool(int nThreads, ThreadFactory threadFactory)

  • 処理内容
    指定されたThreadFactoryを使用して、指定した数のスレッドを保持するスレッドプール
    を作成する
  • パラメータ:
    nThreads プール内のスレッド数
    threadFactory 新規スレッド作成時に使用するファクトリ
  • 戻り値:
    新しく作成されたスレッド・プール

2. void shutdown()

  • 処理内容
    新しいタスクの受け付けを止める命令です。
    すでに実行中 や キューに積まれているタスクは、最後まで実行される。
    それ以降に submit() や execute() でタスクを投げても、
    RejectedExecutionException になる

3. boolean awaitTermination(long timeout, TimeUnit unit)

  • 処理内容
    shutdown() 要求後、指定時間だけスレッドの終了を待つ
  • パラメータ:
    timeout 待機する最長時間
    unit timeout引数の時間単位
  • 戻り値:
    executorが終了した場合はtrue、終了前にタイム・アウトが経過した場合はfalse

4. <T> Future<T> submit(Callable<T> task)

  • 処理内容
    戻り値のある並列タスクを実行して、結果を後で受け取る
  • パラメータ:
    task - 送信するタスク
  • 戻り値:
    タスクの結果を後で受け取るためのオブジェクトを表すFuture

Futureオブジェクトとは

Futureオブジェクトは、ジェネリック型のインターフェースで型引数がタスクの返り値となる。
上記プログラミング例では、戻り値がないので、Future<?>としている。

戻り値がある場合で、結果を得る処理として

//resultは Futureオブジェクト 型パラメータありの場合
System.out.println(result.get(10, TimeUnit.SECONDS));

getメソッドの引数で、タイムアウト値を指定する。
getメソッドを呼び出した場合、メインスレッドがブロックされるため。
完了しなかった場合、TimeoutException例外は発生する。

エピローグ

Javaのスレッドについて、少しづつ初心者を脱却していければいいなと思いつつ、
勉強しているところですが、なかなか道のりは遠そうです...
今回のテーマでもし誤り、もしくはこうしたらいいのに と思うものがあればご指摘頂ければと思います。

以上です。

Discussion