38

JavaのRunnableとインターフェイスの違いを理解しました。CallableJava 1.5 から追加機能がRunnableインターフェースに追加されCallable、下位互換性を維持するために呼び出されました。

私の質問はCallable、インターフェースができたので、常にそれを使用しますか? Callableを使用しない場合と使用する場合のユースケースは何Runnableですか?

これは、それらの違いについての良い記事です)

4

5 に答える 5

34

どちらにも用途があり、どちらも java.util.concurrent の Executor フレームワークでサポートされています。Runnable は以前から存在していますが、現在も使用されており、推奨されていません。

Callable は例外をスローして値を返すことができるため、結果を伴うタスク (ネットワークからのリソースのフェッチ、値の高価な計算の実行など) をより適切に抽象化できます [ Goetz によるJava Concurrency in Practiceから、ブロッホら。al.、Java 並行性に関する標準的な作業]。

したがって、API を設計している場合は、可能であれば Callables を使用することをお勧めします。タスクが値を返さず、例外をスローしないことが確実な場合は、ランナブルも有効な選択です。特に Runnable は Callable に簡単にラップでき、その逆も同様であるため、白黒はありません。

余談ですが、 Callable 実装はthrows Exception;を宣言する必要がないことに注意してください。Callable 自体が宣言しているのは、実装者がチェック済みの例外をスローできるようにするためだけです。ただし、Callable インターフェースのみに依存する Callable の呼び出し元は、例外処理コードを作成する必要があります。
Callable は値を返す必要がないことにも注意してください。Callable を返すように宣言するだけですVoid(大文字の ' V' を使用)。

于 2013-05-26T12:39:56.310 に答える
7

Callable:を使用しないユース ケースであり、のみScheduledExecutorService.scheduleAtFixedRatescheduleWithFixedDelay受け入れますRunnable

于 2013-05-26T07:57:40.247 に答える
6

私は s を好みますが、を にCallableする必要があるまれなケースでは、このようなメソッドを に追加することで両方を簡単に実装できます。CallableRunnablerun()Callable

public void run(){
    try{
        call();
    } catch (Exception e){
        e.printStackTrace(); // or however you log errors
    }
}

Java 8 では、同じことを行うインターフェースを作成することもできます。

public interface CallableRunnable<T> extends Callable<T>, Runnable {
    default void run(){
        try {
            call();
        } catch (Exception e) {
            e.printStackTrace(); // or however you log errors
        }
    }
}

implements Callable<T>次に、それを何かに変更するだけです。そうすればimplements CallableRunnable<T>、ジョブは、いずれかを必要とする任意のメソッドからいつでも呼び出すことができます。もちろん、特定のエラー処理が必要な場合でも、run() メソッドをオーバーライドして、call()メソッドによってスローされた例外を処理できます。そのためのメソッドを実装することもできます。

public interface CallableRunnable<T> extends Callable<T>, Runnable {
    default void run(){
        try {
            call();
        } catch (Exception e) {
            handleCallExceptions(e);
        }
    }

    default void handleCallExceptions(Exception e){
        e.printStackTrace();
    }
}

次に、特別な例外処理は独自のhandleExceptions(Exception)メソッドを実装するだけで済みます...しかし、必要がなければ実装する必要はありません。ロギング フレームワークなどを使用する実装を使用できるため、これを好みます。

于 2014-12-19T05:49:40.320 に答える