2016-05-26 4 views
6

私はJavaにはまったく新しいので、マルチスレッドの概念を説明しながら、マルチスレッドを使用したさまざまな実装を行っていました。 このThe difference between the Runnable and Callable interfaces in Java質問は、2つの違いと使用場所を指定します。呼び出し可能な場所とRunnable Interfaceの使用場所

私の疑問は、CallableがRunnableをすべて実行できるかどうか、なぜ多くの人が呼び出し可能ではなくRunnableを使用するのですか? Runnable Intefaceと比較してCallableインターフェイスを実装する際に余分なオーバーヘッドはありますか?

+1

不要な場合は、Callableを使用しないでください。 [KISS原則](https://people.apache.org/~fhanik/kiss.html)に記載されています。 –

答えて

6

Java 5リリースに入ったjava.util.concurrentパッケージが出る前は、実際に並行計算を行う以外に、Threadを直接操作するオプションはありませんでした。

スレッドを直接操作することができます。一般的に、あなたが関心の明確な分離を提供して何かを、サブクラス化する必要はありません主な理由(好ましい方法だったRunnableを作成することによって、同じことを行うことができ

public class MyThread extends Thread { 
    public void run() { 
     myComputation(); 
    } 
} 

それとも、より良いコードの再利用や:サブクラス化することにより、より良い構成):

どのように使用しても、スレッドを作成、起動、操作、結合する必要がありました。これには欠点があります:いくつのスレッドを作成できますか?これは高価ですか?

また、このAPI自体には、開発者が克服しなければならなかった制限があります。Runnableから値を返す場合はどうすればよいでしょうか。とにかく署名がそれを許可しないのを見ますか? RunnableExceptionで失敗したかどうかはどうすればわかりますか?例外ハンドラなどのスレッドでそれを可能にするものがありますが、それは静かで繰り返しエラーが発生しやすいタスクでした。

java.util.concurrentパッケージに入ります!このすべて(そしてもっと)への答えを提供します!

2つ以上の「作業単位」にスレッドを再利用したい場合は(Runnableかどうか)できます。 「作業単位」が完了したか失敗したかを知りたい場合は可能です。値を返すことができます:できます。他のタスクよりも優先的に動的に優先順位を付けたいですか?確かに。タスクをスケジュールする機能が必要ですか?できる。等々。

Callable S(両方を単一のメソッド・インターフェースは、することができ、これは簡単です!)を使用してRunnable Sを交換し、Future秒の賛成でThreadの操作を停止し、ExecutorServiceに配管を残します。

私の疑問は、CallableがRunnableのすべてを実行できるかどうか、なぜ多くの人が呼び出し可能ではなくRunnableを使用するのですか?

多分古いコード(Java 1.4?)があります。たぶん、彼らはより高いレベルの抽象化の利点を認識しておらず、低いレベルのThreadものを好むかもしれませんか?

一般に、Threadを使用することを好む理由はありません。同時のAPIが来たからです。

Runableインターフェイスと比較してCallableインターフェイスを実装する際に余分なオーバーヘッドはありますか?

Callableを実装する」では、Runnableに対しては存在しません。しかし、内部的にはすべてThreadRunnableに戻ってくるので、新しいCallableのものにはコストがかかります(少なくとも、現在の実装ではこれが行われています)。しかし、実際には、スレッドの再利用が容易であるなどの新しい機能があるため、実際にはパフォーマンスが向上する可能性があります。

はい、コンカレントAPIにはコストがありますが、標準的な使用例では完全に無視されますが、パフォーマンスを含めてさまざまな点で優れた新しい機能もあります。

さらに、既に述べたように、APIからは大きな可能性があります(フォーク/結合フレームワーク、Java 8の並列ストリームを参照)。また、 "カスタム"前記機能のための「自己作成型」並行性コードであり、正しく取得することは難しいとされている。

利益/コスト比は、「新しい」並行APIを完全に支持します。

0

なぜ多くの人が呼び出し可能ではなくRunnableを使用するのですか?

Executableフレームワークに付属しているjdkでは、呼び出し可能なスレッドがより柔軟になり、スレッド実行の柔軟性が向上します。

でCallableインターフェイスを実装する際に余分なオーバーヘッドがありますか?

標準のエグゼキュータのドキュメントに従えば非常に簡単です。

2

重要な違い:Runnableインターフェイスのrun()メソッドはvoidを返します。 Callableインターフェイス内のcall()メソッドは、タイプTのオブジェクトを返します。これにより、応答オブジェクトに簡単にアクセスできます。

Runnableの具体的な実装では、プライベートデータメンバーを作成してゲッターを提供することで同じことができますが、構文的な砂糖は甘いです。

4

私の疑問は、CallableがRunnableをすべて実行できるかどうか、なぜ多くの人が呼び出し可能ではなくRunnableを使用するのですか? Runnable Intefaceと比較してCallableインターフェースを実装する際に余分なオーバーヘッドはありますか?

  1. 使用Runnable火災のためのインタフェースとは、タスクの実行結果に興味がない場合は特に、呼び出しを忘れています。
  2. Callableインターフェイスの実装に余分なオーバーヘッドはありません。

両方がそのインスタンス潜在的に別のスレッドによって実行されるクラスのために設計されていることを文書page

から重要な違いは、Callableインターフェースは、Runnableと同様です。ただし、Runnableは結果を返しません。チェック例外をスローすることはできません。

Callableが内部RunnableFuture<T>

0

を使用してAbstractExecutorService

public Future<?> submit(Runnable task) { 
    if (task == null) throw new NullPointerException(); 
    RunnableFuture<Object> ftask = newTaskFor(task, null); 
    execute(ftask); 
    return ftask; 
} 


public <T> Future<T> submit(Callable<T> task) { 
    if (task == null) throw new NullPointerException(); 
    RunnableFuture<T> ftask = newTaskFor(task); 
    execute(ftask); 
    return ftask; 
} 

のソースコードを確認できます私は、呼び出し可能にすることができる場合私の疑いがあるCallableタスクの実行中に任意のオーバーヘッドが表示されませんRunnableの全てをやっているのですが、なぜ多くの人が呼び出し可能ではなくRunnableを使うのですか?

「Javaにはなぜ静的型があるのですか」という質問には同じ質問があります。インターフェイスは、コンパイル時の型シグネチャの宣言です。任意の2つのインタフェースの唯一の違いは、引数のコンパイル時の型と戻り値です。

Javaにはなぜ静的型があるのですか?残念ながら、その質問はStackOverflowの範囲外です。 Googleを使用して、静的に型指定された言語と動的に型指定された言語に関するすべてを見つけることができます。

また、別の世界を垣間見たい場合は、Rubyコードを書くこともできます。 Rubyには静的型がないため、インタフェースはありません。 Rubyプログラマーは、Googleにとってもう一つの良い言い方である「Duck Typing」について語ります。

関連する問題