24

CompletableFutureJava 8 がJava メモリ モデルとどのように相互作用するかを理解しようとしています。プログラマーの正気のために、理想的には次のことが当てはまるように思えます。

  1. 完了に依存するステージが実行されるCompletableFuture 前に発生するスレッド内のアクション
  2. 完了を登録するスレッド内のアクションは、完了依存ステージが実行される前に発生する依存ステージを作成します

java.util.concurrent のドキュメントには、次のようなメモがあります。

への送信前のスレッド内のアクションは、その実行が開始される前に発生Runnableします。に提出されたについても同様です。Executor CallableExecutorService

これは、future を完了するスレッドが完了依存ステージを実行するか、Executor. 一方、CompletableFuture のドキュメントを読んだ後、私はそれについてよくわかりません:

非非同期メソッドの依存完了のために提供されるアクションは、現在の を完了するスレッドCompletableFuture、または完了メソッドの他の呼び出し元によって実行される場合があります。

それは私の質問に私をもたらします:

  1. 上記の 2 つの仮定上の特性は正しいですか?
  2. で作業するときのメモリ可視性の保証の有無について、特定のドキュメントはどこかにありCompletableFutureますか?

補遺:

具体的な例として、次のコードを検討してください。

List<String> list1 = new ArrayList<>();
list1.add("foo");

CompletableFuture<List<String>> future =
        CompletableFuture.supplyAsync(() -> {
            List<String> list2 = new ArrayList<>();
            list2.addAll(list1);
            return list2;
        });

"foo"への追加list1がラムダ関数に表示されることが保証されていますか? list1への追加list2が の依存ステージに表示されることが保証されていfutureますか?

4

1 に答える 1

5
  1. はい、あなたの仮説はどちらも正しいです。その理由は、 のすべての*Async()メソッドCompletableFutureが a を使用しjava.util.concurrent.Executorて非同期呼び出しを行うためです。指定しない場合、これは、共通プール、またはタスクごとに新しいスレッドを作成する Executor (共通プールのサイズを 0 または 1 に制限する場合)、またはユーザー提供の Executor のいずれかになります。すでにわかっているように、のドキュメントには次のように書かれていExecutorます。

    Runnable オブジェクトを Executor に送信する前のスレッド内のアクションは、おそらく別のスレッドで実行が開始される前に発生します。

    したがって、あなたの例では、ラムダ"foo"の一部であり、後続の段階で表示されることが保証されています。list1list2

  2. これは基本的に のドキュメントでカバーされていますExecutor

于 2015-12-23T23:00:07.440 に答える