Java:「スレッドプール」と「ExecutorService」
プロローグ
こんにちは、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