Skip to content
閲覧中:
13.0

13.0

Java の Runnable / Callable / Thread の違い

Java では並列処理・非同期処理を行うために Runnable、Callable、Thread がよく使われます。

それぞれ役割が異なります。

まず結論

名前 役割 戻り値 例外 実行方法
Runnable 処理だけ実行 なし (void) checked例外を投げにくい Thread や ExecutorService
Callable 値を返す処理 あり Exception を投げられる ExecutorService
Thread スレッドそのもの なし 普通に可能 start()

イメージ

Text Only
Thread
 └─ Runnable を実行できる
ExecutorService
 ├─ Runnable を実行
 └─ Callable を実行

1. Runnable

特徴

  • 一番基本的
  • 戻り値なし
  • run() を実装
  • Java 1.0 から存在
  • 軽量な「処理」

定義

Java
@FunctionalInterface
public interface Runnable {
    void run();
}

サンプル

Java
public class Main {
    public static void main(String[] args) {
        Runnable task = () -> {
            System.out.println("Runnable 実行");
        };
        Thread thread = new Thread(task);
        thread.start();
    }
}

特徴まとめ

メリット

  • シンプル
  • ラムダ式と相性が良い
  • 軽い

デメリット

  • 戻り値を返せない
  • checked例外をそのまま投げられない

2. Callable

特徴

  • 戻り値を返せる
  • 例外を投げられる
  • ExecutorService と組み合わせる
  • Java 5 から追加

定義

Java
@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

サンプル

import java.util.concurrent.*; public class Main { public static void main(String[] args) throws Exception { Callable task = () -> { return 100; }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(task); Integer result = future.get(); System.out.println(result); executor.shutdown(); } }

実行結果

Text Only
100

Future とは?

Callable の結果を後で受け取るためのオブジェクトです。

Text Only
Callable → Future → 結果取得

よく使うメソッド

メソッド 意味
get() 結果取得
isDone() 終了確認
cancel() キャンセル

Runnable と Callable の比較

項目 Runnable Callable
戻り値 なし あり
メソッド run() call()
checked例外 投げにくい 投げられる
使用頻度 高い 高い
ExecutorService

3. Thread

特徴

Thread は

「実際のスレッドそのもの」

です。

Thread を継承する例

Java
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread 実行");
    }
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();
    }
}

start() と run() の違い

Text Only
start()

t.start();

  • 新しいスレッドを作る
  • 並列実行

Text Only
run()

t.run();

  • 普通のメソッド呼び出し
  • 並列にならない

Thread の問題点

継承を使ってしまう

Java は単一継承なので、

Text Only
class A extends Thread

にすると他を継承できません。

そのため現在は

Text Only
Runnable + ExecutorService

が主流です。

現代Javaでのおすすめ

|用途|おすすめ |単純な並列処理|Runnable |結果が欲しい|Callable |本格運用|ExecutorService |Thread継承|あまり使わない

ExecutorService が重要

現在のJavaでは、

Thread を直接作る

より、

ExecutorService に仕事を投げる

方が一般的です。

Runnable を ExecutorService で実行

import java.util.concurrent.*; public class Main { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(3); Runnable task = () -> { System.out.println( Thread.currentThread().getName() ); }; executor.submit(task); executor.shutdown(); } }

Callable を複数実行

import java.util.concurrent.; import java.util.; public class Main { public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newFixedThreadPool(3); List> tasks = List.of( () -> 10, () -> 20, () -> 30 ); List> futures = executor.invokeAll(tasks); for (Future f : futures) { System.out.println(f.get()); } executor.shutdown(); } }

Runnable と Callable の覚え方

名前|覚え方 Runnable|「走るだけ」 Callable|「電話して結果を返す」

Thread のライフサイクル

NEW ↓ RUNNABLE ↓ RUNNING ↓ TERMINATED

Java Gold 向け重要ポイント

Runnable

  • void run()
  • 引数なし
  • 戻り値なし

Callable

  • V call() throws Exception
  • 戻り値あり
  • checked例外OK

Future

  • get()
  • isDone()
  • cancel()

試験でよく出る罠

run() を直接呼ぶ

thread.run();

これは並列処理ではない。

start() を2回呼ぶ

thread.start(); thread.start(); IllegalThreadStateException

になる。

まとめ

項目|Runnable|Callable|Thread 正体|タスク|タスク|スレッド 戻り値|×|○|× checked例外|×|○| 主な用途|軽い処理|結果取得|スレッド制御 現代Java|◎|◎|△

現代Javaの基本形

Text Only
ExecutorService
    + Runnable
    + Callable
    + Future

この組み合わせが最重要です。