Java Gold SE11対策:戻り値のある非同期処理 ― Callable / Future の基本と使い方

アイキャッチ画像

Runnable は、スレッドを使った処理を書くには便利ですが、実行結果(戻り値)を返すことができません

Runnable task = () -> {

    // 処理を書くが、戻り値を返せない

};

でも、実務では「スレッドで重い処理をして、結果を取得したい」というケースが多くあります。

そこで登場:Callable / Future

用語役割
Callable<T>戻り値を持つタスクの定義
Future<T>結果をあとで受け取るための器

Callable<Integer> task = () -> {

    Thread.sleep(1000);

    return 42;

};

🔁 Runnable が void run() を持つのに対して、Callable は T call() を持ちます!

実際の使い方:ExecutorService + Callable + Future

import java.util.concurrent.*;

public class CallableExample {

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newSingleThreadExecutor();

        Callable<Integer> task = () -> {

            Thread.sleep(1000);

            return 42;

        };

        Future<Integer> future = executor.submit(task); // スレッドで実行

        System.out.println(“処理中…”);

        Integer result = future.get(); // 結果が返るまで待つ(ブロッキング)

        System.out.println(“結果: ” + result);

        executor.shutdown();

    }

}

Future.get() の注意点

  • .get() を呼ぶと、タスクが終わるまで待機(=ブロッキング)します
  • 例外処理が必要:InterruptedException, ExecutionException

try {

    Integer result = future.get();

} catch (InterruptedException | ExecutionException e) {

    e.printStackTrace();

}

Runnable との違いまとめ

項目RunnableCallable
戻り値なし(void)あり(T型)
例外投げられないException を throw できる
メソッド名run()call()
スレッド生成法Thread または ExecutorService.submit(Runnable)ExecutorService.submit(Callable)
結果の取得不可Future.get() で取得可能

Java Gold SE11試験での狙われポイント

  • submit(Runnable) vs submit(Callable) の違い
  • Future.get() のブロッキング挙動
  • Callable の call() は例外を投げられる点
  • シャットダウン忘れ(executor.shutdown())

まとめ

用語役割
Callable戻り値と例外が扱えるスレッドタスク
Future非同期で処理した結果を受け取る器
ExecutorServiceスレッドプールでタスクを管理する仕組み
get()タスクの完了を待ち、結果を取り出す(ブロッキング)