4

私は CompletableFutures について多くのことを読んできましたが、CompletableFuture は Future のように基礎となる計算コードにアクセスできないという事実に焦点を当てています。では、completableFuture が関連付けられている任意のタスク内から、どうすれば complete() または cancel() を通知できますか (または、外部から計算を中断したい場合は isCancelled() を確認します)。

編集:私を混乱させることの1つは、CFが構成可能性または手動設定可能性のいずれかの代替手段よりも使用されていることです。

CompletableFuture.runAsync(() -> { 
                              if(myCondition) CF_REF?.complete();
                              else            CF_REF?.exceptionally();
                           }).thenApply(() -> {
                                        if (myOtherCondition) CF_REF_2?.complete();
 (...)

同時に「完成可能」+「構成可能」ではない方法で設計するポイントは何ですか?

CF が架空の CompletableCallable に似たインターフェイスを入力として使用したかのようにそれらを使用する方法を見つけたいのですが、方法がわかりません。Callables/Runnables の代わりのようなものなFunction<CompletableFuture,T>ので、次のように使用できます。

CompletableFuture CF_REF_BIS = CompletableFuture.runAsync((CF_REF) -> { 
                                  if(myCondition) CF_REF.complete();
                                  else CF_REF.exceptionally();
                               });

CF_REF_BIS.thenApply(...)

コードが計算されるとき、まさに CF_REF_BIS 参照が、スコープ全体でアクセスする必要なく、将来の計算で実際に CF_REF として渡されるものとして、内部実行メカニズムによって返されます。

つまり、新しい CompeltableCallable() を作成し、任意のスレッドが CompletableFuture セマフォにアクセスできる任意の場所に n 回送信するだけで、計算コードを非匿名化して再利用できることを意味します。

例えば:

CompletableFuture CF_REF = CompletableFuture.runAsync(myCompletableCallable)
             .thenApply(myCompletableCallable) //again
             .thenApply(anotherCompletableCallable); 

その必要性を達成する方法はありますか?私は何かを忘れていますか?私のアプローチに根本的な矛盾はありますか? Java CompletableFuture はまだ中途半端な便利な設計ですか?

4

1 に答える 1

2

javadoc を見てください。

CompletableFuture#complete()

まだ完了していない場合は、get()および関連するメソッドによって返される値を指定された値に設定します。

CompletableFuture#cancel()

まだ完了していない場合は、. で完了CompletableFutureCancellationExceptionます。まだ完了していないDependentCompletableFutureも例外的に完了し、 CompletionExceptionこれにより が発生しますCancellationException

[...]

パラメーター:

mayInterruptIfRunning - 割り込みは処理の制御に使用されないため、この実装ではこの値は効果がありません。

CompletableFutureオブジェクトは、それらへの到達可能な参照を持つ可能性のあるスレッドとはまったく関係ありません。つまり、これらのオブジェクトは、スレッドに通知するためのものではありません。このタイプのフューチャーは基本的に、リスナーを登録するオプションを備えた結果のホルダーです。

とのすべての動作はwhenXyz、オブジェクトthenAbcに登録されCompletableFutureます。その振る舞いがいつ実行されるかは、どのスレッドが Future を (成功または例外的に) 完了したか、継続が*Asyncメソッドに登録されたかどうかなど、さまざまな要因に依存します。これはjavadocに記載されています。


たとえば、 を作成し、CompletableFutureそれをいくつかのスレッドに渡します。おそらく、これらのスレッドのいずれかがcompleteそれを行います。これは他のスレッドには影響しません。彼らは今でも、自分がしていたこと、またはやろうとしていたことを正確に続けています。

public static void main(String[] args) throws Exception {
    CompletableFuture<String> promise = new CompletableFuture<>();
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    Runnable action = () -> {
        if (promise.complete("done")) {
            System.out.println("completed by " + Thread.currentThread());
        } else {
            System.out.println("somebody got there first");
        }
    };
    executorService.submit(action);
    executorService.submit(action);
    executorService.submit(action);

    executorService.shutdown();
    executorService.awaitTermination(100, TimeUnit.MILLISECONDS);
    System.out.println(promise.get());
}
于 2015-11-30T02:38:51.397 に答える