2016-03-28 7 views
14

ビットはこれらの2つの静的メソッドである私を混乱しましたか? Callableを使用するのは自然ではありませんか?それは値を返すRunnableの類推ですか?これはサプライヤが処理できない例外を投げないためですか?CompletableFuture supplyAsync

+0

を参照しますプログラマーを混乱させることなく、同じ仕事をするFunc <> 'インターフェース。そして、彼らは、同じシグネチャであるが名前が異なるメソッドのために機能的なインターフェイスを広げました。彼らはおそらく、プログラマが彼に働く精神モデルを与えることによってプログラマを助けると思ったが、そうではない。それは単なる小さなPITAである。 – davidbak

答えて

7

短い答え

いいえ、それはCompletableFuture.supplyAsyncCallable代わりのSupplierを使用する方が自然ではありません。この議論はほぼ完全にセマンティクスに関するものなので、それでも後で納得できないと感じるのであれば問題ありません。

ロング答え

CallableSupplier機能インターフェース/ SAMタイプは(しゃれを許し)機能に実質的に等価であるが、その起源及び使用目的が異なります。

Callableは、java.util.concurrentパッケージの一部として作成されました。このパッケージは、Java 8のラムダ式の膨大な変更の前に提供され、もともとは、実用的なマルチスレッドの古典的モデルから大きく逸脱することなく、並行コードの作成に役立つさまざまなツールに集中していました。

Callableの主な目的は、別のスレッドで実行できる結果を返すアクションを抽象化することでした。 CallableさんのJavadocから:

Callableインターフェースは、Runnableに類似しているの両方を そのインスタンス潜在 別のスレッドによって実行されるクラスのために設計されていることです。

Supplierjava.util.functionパッケージの一部として作成されました。このパッケージは、前述のJava 8の変更の不可欠な部分として提供されました。ラムダ式とメソッド参照の対象となる共通の関数型を提供します。

このようなタイプの1つは、結果を返すパラメータのない関数です(つまり、何らかのタイプを提供する関数またはSupplier関数)。

だからなぜSupplierで、Callableではないのですか?

CompletableFutureのJava 8で前述の変化に触発され、それは、開発者が機能的、暗黙的並列化の方法で彼のコードを構築することができ、代わりに明示的にその中の同時実行を処理し、java.util.concurrentパッケージへの追加の一部です。

そのsupplyAsyncメソッドは、この結果に到達するためのアクションではなく、特定のタイプの結果とその結果に興味がある方法を提供する方法を必要とします。また、例外的な補完についても必ずしも気にする必要はありません(を参照してください...段落)。Runnableはないパラメータに使用される場合

はさらに、無結果機能インタフェースは、Callableを無パラメータ、単結果官能インターフェイスに使用されるべきではありませんか?

必ずしもそうではありません。

パラメータを持たず、結果を返さない(したがって、外部コンテキストで副作用によって完全に機能する)関数の抽象化は、java.util.functionに含まれていませんでした。これは、そのような機能的インタフェースが必要な場合はいつでも(少し面倒なことに)Runnableが使用されることを意味します。

Callable.call()でスローされることが確認されたExceptionはどうなりますか?

CallableSupplierの間の意味的相違の小さな兆候です。

Callableは、別のスレッドで実行できるアクションであり、実行の結果としてその副作用を検査することができます。すべてがうまくいくならば、特定の型の結果が得られますが、特にマルチスレッドのコンテキストでいくつかのアクションを実行するときに例外的な状況が発生する可能性があるため、そのような例外的な状況を定義して処理することもできます。

Supplierは、何らかのタイプのオブジェクトを提供するための関数です。例外的な状況は、必ずしもSupplierの直接消費者としてのあなたの責任となるべきではありません。これは、そうからである。

  1. ...機能インターフェースは、多くの場合、データの作成または変異のための多段階プロセスにおいて特定の段階を定義するために使用され、そしてException Sを処理する別個の段階であることができ、場合にあなたが気彼らは一般的に ``アクション<> `と名付けたのC#、異なるように持っていたので、明示的にException sが大幅に機能インタフェース、ラムダ式と方法の表現力を低減取り扱い
  2. は...
+0

主な違いは意味論的な側面にあり、実用的ではないというあなたの主張は正しいと思います。意味的に_CallAsync_という名前のメソッドを使用しても、結果を返すものではありません。 –

+0

IMO同じ機能性の異なるメソッド(例えば、 'call()'と 'get()')を別々に名前を付けた機能的なインターフェースを持つことの全体的な考え方は悪い考えであり、具体的には、あなたが呼び出す必要のある方法が何であるかを覚えておいて、Callableなどが必要なメソッドに持っているサプライヤを簡単に送ることができないようにすることです。あなたが記述する意図された「意味」はすべてコンパイラが強制するものとは何の関係もなく、Javaのドキュメントでは記述が不十分であるか、まったく記述されていません。 C#はそれをより良くしました。 – davidbak