536

RunnableJava で並行スレッドを設計する際にとCallableインターフェースを使用することの違いは何ですか?

4

14 に答える 14

478

ここで説明を参照してください。

Callable インターフェースは Runnable と似ており、どちらもインスタンスが別のスレッドによって実行される可能性があるクラス用に設計されています。ただし、Runnable は結果を返さず、チェック例外をスローできません。

于 2008-09-26T19:02:17.363 に答える
295

Runnableとのアプリケーションの違いは何ですかCallable。に存在する戻りパラメータとの違いのみCallableですか?

基本的に、はい。この質問への回答を参照してください。そしてのjavadocCallable

Callableそれがすべてできるのなら、両方を持つ必要は何Runnableですか?

Runnableインターフェイスはすべてを実行できるわけではないためCallableです。

Runnableは Java 1.0 から存在していますがCallable、Java 1.5 でのみ導入されました ...Runnableサポートされていないユースケースを処理するためです。理論的には、Java チームはメソッドの署名を変更できたかもしれませんがRunnable.run()、これにより 1.5 より前のコードとのバイナリ互換性が失われ、古い Java コードを新しい JVM に移行するときに再コーディングが必要になります。それはBIG NO-NOです。Java は下位互換性を保つよう努めています...そしてそれは、ビジネス コンピューティングにおける Java の最大のセールス ポイントの 1 つです。

そして、明らかに、タスクが結果を返したり、チェック済みの例外をスローしたりする必要がないユースケースがあります。これらのユースケースでは、メソッドからダミーの ( ) 値を使用して返すRunnableよりも、使用する方が簡潔です。Callable<Void>nullcall()

于 2010-10-17T06:44:49.880 に答える
38

これらの違いをもう少し説明できる別のブログでこれを見つけました:

どちらのインターフェースも、別の実行スレッドで実行したいクラスによって実装されていますが、2 つのインターフェースには次のような違いがほとんどありません。

  • インスタンスは typeのCallable<V>結果を返しますが、インスタンスは返しVませRunnableん。
  • Callable<V>インスタンスはチェック済み例外をスローする場合がありますが、インスタンスRunnableはできません。

Java の設計者は、インターフェイスの機能を拡張する必要性を感じていましたが、Runnableインターフェイスの使用に影響を与えたくありませんでした。おそらくそれが、既存のインターフェイスを変更するよりも、Java 1.5 で名前をRunnable付けた別のインターフェイスを持つことにした理由です。Callable既存のRunnable

于 2010-01-27T17:35:29.817 に答える
33

Runnable と Callable を使用する場所を見てみましょう。

Runnable と Callable はどちらも、呼び出しスレッドとは異なるスレッドで実行されます。ただし、Callable は値を返すことができますが、Runnable はできません。では、これが実際に適用されるのはどこでしょうか。

Runnable : ファイア アンド フォーゲット タスクがある場合は、Runnable を使用します。コードを Runnable 内に配置し、run() メソッドが呼び出されると、タスクを実行できます。タスクを実行するとき、呼び出しスレッドは実際には気にしません。

Callable : タスクから値を取得しようとしている場合は、Callable を使用します。Callable だけでは機能しません。Callable をラップして future.get () で値を取得する Future が必要になります。ここでは、Future が結果を返して Callable の call() メソッドの実行を待機するまで、呼び出しスレッドはブロックされます。

Runnable と Callable の両方のラップされたメソッドが定義されているターゲット クラスへのインターフェイスについて考えてみてください。呼び出しクラスは、どれが Runnable でどれが Callable であるかを知らずに、インターフェイス メソッドをランダムに呼び出します。Runnable メソッドは、Callable メソッドが呼び出されるまで非同期で実行されます。ここでは、ターゲット クラスから値を取得しているため、呼び出し元のクラスのスレッドがブロックされます。

注 : ターゲット クラス内では、Callable と Runnable を単一のスレッド エグゼキューターで呼び出すことができ、このメカニズムをシリアル ディスパッチ キューに似たものにします。したがって、呼び出し元が Runnable でラップされたメソッドを呼び出す限り、呼び出し元のスレッドはブロックされることなく非常に高速に実行されます。Future メソッドでラップされた Callable を呼び出すとすぐに、キューに入れられた他のすべての項目が実行されるまでブロックする必要があります。その場合にのみ、メソッドは値を返します。これは同期メカニズムです。

于 2014-10-03T16:40:42.883 に答える
18

Callableインターフェイスcall()はメソッドを宣言し、オブジェクト call() の型が返されるようにジェネリックを提供する必要があります -

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Runnable一方run()、実行可能なスレッドを作成し、その上で start() を呼び出すときに呼び出されるメソッドを宣言するインターフェイスです。run() を直接呼び出すこともできますが、それは run() メソッドを実行するだけで同じスレッドです。

public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used 
     * to create a thread, starting the thread causes the object's 
     * <code>run</code> method to be called in that separately executing 
     * thread. 
     * <p>
     * The general contract of the method <code>run</code> is that it may 
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

いくつかの注目すべき違いを要約すると、

  1. Runnableオブジェクトは結果を返しませんが、オブジェクトCallableは結果を返します。
  2. オブジェクトは例外をスローできますが、オブジェクトはRunnableチェック例外をスローできませんCallable
  3. このRunnableインターフェースは Java 1.0 から存在していますがCallable、Java 1.5 でのみ導入されました。

いくつかの類似点が含まれます

  1. Runnable または Callable インターフェースを実装するクラスのインスタンスは、別のスレッドによって実行される可能性があります。
  2. Callable および Runnable インターフェースの両方のインスタンスは、submit() メソッドを介して ExecutorService によって実行できます。
  3. どちらも関数型インターフェースであり、Java8 以降の Lambda 式で使用できます。

ExecutorService インターフェイスのメソッドは

<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
于 2014-12-27T07:24:17.893 に答える
15

Oracleドキュメントからのこれらのインタフェースの目的:

実行可能なインターフェイスは、インスタンスがThread. クラスは、 と呼ばれる引数のないメソッドを定義する必要がありますrun

Callable : 結果を返し、例外をスローする可能性があるタスク。実装者は、call という引数のない単一のメソッドを定義します。インタフェースは、インスタンスが別のスレッドによって実行される可能性のあるクラス用に設計されているという点で に似Callableています。Runnableただし、 ARunnableは結果を返さず、チェック例外をスローできません。

その他の違い:

  1. ThreadRunnableを作成するために渡すことができます。ただし、パラメーターとして渡して新しいスレッドを作成することはできません。インスタンスにのみ Callable を渡すことができます。CallableExecutorService

    例:

    public class HelloRunnable implements Runnable {
    
        public void run() {
            System.out.println("Hello from a thread!");
        }   
    
        public static void main(String args[]) {
            (new Thread(new HelloRunnable())).start();
        }
    
    }
    
  2. Runnableファイア アンド フォーゲット コールに使用します。Callable結果を確認するために使用します。

  3. Callableとは異なり、 invokeAllメソッドに渡すことができますRunnable。メソッドinvokeAnyinvokeAll使用して、最も一般的に役立つ形式の一括実行を実行します。タスクのコレクションを実行してから、少なくとも 1 つまたはすべてのタスクが完了するのを待ちます。

  4. 些細な違い: 実装するメソッド名 => run()forRunnablecall()for Callable.

于 2016-02-15T10:59:17.890 に答える
13

ここですでに述べたように、Callableは比較的新しいインターフェースであり、並行性パッケージの一部として導入されました。CallableとRunnableの両方をエグゼキュータで使用できます。クラススレッド(Runnable自体を実装する)はRunnableのみをサポートします。

Runnableは引き続きエグゼキュータで使用できます。Callableの利点は、エグゼキュータに送信して、実行が終了したときに更新される将来の結果をすぐに返すことができることです。Runnableでも同じことが実装できますが、この場合、結果を自分で管理する必要があります。たとえば、すべての結果を保持する結果キューを作成できます。他のスレッドはこのキューで待機し、到着した結果を処理できます。

于 2010-10-17T07:16:09.763 に答える