ビットはこれらの2つの静的メソッドである私を混乱しましたか? Callableを使用するのは自然ではありませんか?それは値を返すRunnableの類推ですか?これはサプライヤが処理できない例外を投げないためですか?CompletableFuture supplyAsync
答えて
短い答え
いいえ、それはCompletableFuture.supplyAsync
にCallable
代わりのSupplier
を使用する方が自然ではありません。この議論はほぼ完全にセマンティクスに関するものなので、それでも後で納得できないと感じるのであれば問題ありません。
ロング答え
Callable
とSupplier
機能インターフェース/ SAMタイプは(しゃれを許し)機能に実質的に等価であるが、その起源及び使用目的が異なります。
Callable
は、java.util.concurrent
パッケージの一部として作成されました。このパッケージは、Java 8のラムダ式の膨大な変更の前に提供され、もともとは、実用的なマルチスレッドの古典的モデルから大きく逸脱することなく、並行コードの作成に役立つさまざまなツールに集中していました。
Callable
の主な目的は、別のスレッドで実行できる結果を返すアクションを抽象化することでした。 Callable
さんのJavadocから:
Callable
インターフェースは、Runnable
に類似しているの両方を そのインスタンス潜在 別のスレッドによって実行されるクラスのために設計されていることです。
Supplier
はjava.util.function
パッケージの一部として作成されました。このパッケージは、前述のJava 8の変更の不可欠な部分として提供されました。ラムダ式とメソッド参照の対象となる共通の関数型を提供します。
このようなタイプの1つは、結果を返すパラメータのない関数です(つまり、何らかのタイプを提供する関数またはSupplier
関数)。
だからなぜSupplier
で、Callable
ではないのですか?
CompletableFuture
のJava 8で前述の変化に触発され、それは、開発者が機能的、暗黙的並列化の方法で彼のコードを構築することができ、代わりに明示的にその中の同時実行を処理し、java.util.concurrent
パッケージへの追加の一部です。
そのsupplyAsync
メソッドは、この結果に到達するためのアクションではなく、特定のタイプの結果とその結果に興味がある方法を提供する方法を必要とします。また、例外的な補完についても必ずしも気にする必要はありません(を参照してください...段落)。Runnable
はないパラメータに使用される場合
はさらに、無結果機能インタフェースは、Callable
を無パラメータ、単結果官能インターフェイスに使用されるべきではありませんか?
必ずしもそうではありません。
パラメータを持たず、結果を返さない(したがって、外部コンテキストで副作用によって完全に機能する)関数の抽象化は、java.util.function
に含まれていませんでした。これは、そのような機能的インタフェースが必要な場合はいつでも(少し面倒なことに)Runnable
が使用されることを意味します。
Callable.call()
でスローされることが確認されたException
はどうなりますか?
Callable
とSupplier
の間の意味的相違の小さな兆候です。
Callable
は、別のスレッドで実行できるアクションであり、実行の結果としてその副作用を検査することができます。すべてがうまくいくならば、特定の型の結果が得られますが、特にマルチスレッドのコンテキストでいくつかのアクションを実行するときに例外的な状況が発生する可能性があるため、そのような例外的な状況を定義して処理することもできます。
Supplier
は、何らかのタイプのオブジェクトを提供するための関数です。例外的な状況は、必ずしもSupplier
の直接消費者としてのあなたの責任となるべきではありません。これは、そうからである。
- ...機能インターフェースは、多くの場合、データの作成または変異のための多段階プロセスにおいて特定の段階を定義するために使用され、そして
Exception
Sを処理する別個の段階であることができ、場合にあなたが気彼らは一般的に ``アクション<> `と名付けたのC#、異なるように持っていたので、明示的にException
sが大幅に機能インタフェース、ラムダ式と方法の表現力を低減取り扱い - は...
主な違いは意味論的な側面にあり、実用的ではないというあなたの主張は正しいと思います。意味的に_CallAsync_という名前のメソッドを使用しても、結果を返すものではありません。 –
IMO同じ機能性の異なるメソッド(例えば、 'call()'と 'get()')を別々に名前を付けた機能的なインターフェースを持つことの全体的な考え方は悪い考えであり、具体的には、あなたが呼び出す必要のある方法が何であるかを覚えておいて、Callableなどが必要なメソッドに持っているサプライヤを簡単に送ることができないようにすることです。あなたが記述する意図された「意味」はすべてコンパイラが強制するものとは何の関係もなく、Javaのドキュメントでは記述が不十分であるか、まったく記述されていません。 C#はそれをより良くしました。 – davidbak
を参照しますプログラマーを混乱させることなく、同じ仕事をするFunc <> 'インターフェース。そして、彼らは、同じシグネチャであるが名前が異なるメソッドのために機能的なインターフェイスを広げました。彼らはおそらく、プログラマが彼に働く精神モデルを与えることによってプログラマを助けると思ったが、そうではない。それは単なる小さなPITAである。 – davidbak