Javaの並行処理ライブラリ(ExecutorService、Callableなど)

Javaの並行処理を効率的かつ安全に行うために、java.util.concurrentパッケージには複数の高水準なライブラリが用意されています。その中でも特に重要なのが、ExecutorServiceCallable などのインタフェースやクラス群です。これらを用いることで、低レベルのThreadクラスを直接扱う必要がなくなり、より柔軟でスケーラブルな並行処理が可能となります。


1. Executor インタフェース

説明

  • Executorは、タスク(Runnable)を非同期で実行する単純なインタフェースです。

  • void execute(Runnable command) メソッドのみを定義しています。

java
Executor executor = Executors.newSingleThreadExecutor(); executor.execute(() -> System.out.println("タスク実行"));

2. ExecutorService インタフェース

説明

  • Executorの拡張インタフェースであり、スレッドプールを管理し、非同期タスクの実行を制御できます。

  • submit()メソッドにより、RunnableCallableタスクを送信できます。

  • 結果の取得、シャットダウン、タスクのキャンセルなどを制御可能です。

主なメソッド

メソッド 説明
submit(Runnable) タスクを送信し、Future<?>を返す
submit(Callable<T>) タスクを送信し、Future<T>を返す
shutdown() 新規タスクの受け入れを停止し、既存タスクの完了を待つ
shutdownNow() 実行中のタスクを強制停止し、未開始のタスクをキャンセル
invokeAll() 複数のタスクを同時に実行し、全ての結果を待つ
invokeAny() 複数のタスクのうち、最初に完了したタスクの結果を返す

3. Callable インタフェース

説明

  • Runnableと似ていますが、戻り値を返すことができます。

  • call()メソッドを定義し、例外もスロー可能です。

java
Callable<Integer> task = () -> { Thread.sleep(1000); return 42; };

4. Future インタフェース

説明

  • submit()invokeAll()の結果を表すオブジェクトです。

  • 非同期処理の結果を取得したり、処理の状態をチェックしたり、キャンセルできます。

主なメソッド

メソッド 説明
get() タスク完了まで待機して結果を取得
get(timeout, unit) タイムアウト付きで結果を取得
isDone() タスクの完了状態を返す
cancel(mayInterruptIfRunning) タスクのキャンセルを試みる
isCancelled() タスクがキャンセルされたかを確認する

5. 実例:ExecutorService + Callable + Future

java
import java.util.concurrent.*; public class ConcurrentExample { public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newFixedThreadPool(2); Callable<String> task = () -> { Thread.sleep(1000); return "完了しました"; }; Future<String> future = executor.submit(task); // 結果の取得 String result = future.get(); // ここで最大1秒待つ System.out.println(result); executor.shutdown(); } }

6. 利点と用途

特徴 説明
柔軟なスレッド管理 スレッドの使い回し、最大スレッド数の制御などが可能
戻り値のある処理 Callableによる戻り値と例外処理のサポート
スケーラブルな設計 大量のタスクを効率的に処理できるスレッドプール設計
安全性の向上 明示的な同期なしにタスクを分離して実行可能

まとめ

JavaのExecutorServiceCallableは、従来のスレッドよりも安全かつ効率的に並行処理を行うための仕組みを提供します。非同期タスクの送信、結果の取得、スレッドプールによるリソースの最適化が可能になり、大規模な並列処理でもコードの可読性とメンテナンス性を高めることができます。

生成日:2025/05/03