67874


現在Java,Eclipse,Java1.8でCompletabelFutureによる非同期処理を勉強しています。

**以下のサイトにある次のコードを実装したのですが、コンソール出力されません。  
なぜでしょうか？**（サイト上ではコンソール出力されると書いているのですが）

[CompletableFutureの公式ドキュメントを読んでも分からないので
Java逆引きレシピを片手に理解する](https://qiita.com/bonobono555/items/97a678d6530c8a0b939d#thenapply%E3%81%AE%E5%A0%B4%E5%90%88)

[code]

        public class CompletableFutureTest {
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
    
            CompletableFuture<String> future1 = CompletableFuture.supplyAsync(
                    () -> {
                        // 時間のかかる処理
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return "java1";
                    });
    
            // thenApplyの場合
            future1
                    .thenApply(
                            new Function<String, String>() {
                                @Override
                                public String apply(String res) {
                                    return res; // resには、future1のreturnで定義した「java1」が入っている
                                }
                            })
                    .thenApply(
                            res -> {
                                return res; // resには1回目のthenApplyの戻り値の「java1」が入っている
                            })
                    .thenAccept(
                            new Consumer<String>() {
                                @Override
                                public void accept(String res) {
                                    System.out.println(res); // resには2回目のthenApplyの戻り値の「java1」が入っており、コンソールに出力される
                                }
                            });
        }
    }
    
[/code]

ちなみにThread.sleep(1000);をThread.sleep(1);のように短くしたり、コメントアウトするとコンソール出力されます。動きとして、１秒後に返される戻り値を待てずにthenApply以降の処理が実行されているのかなと思います。

thenApply自体は前の処理の完了は待たないのでしょうか？「このステージが正常に完了したときに、このステージの結果を指定された関数への引数に設定して実行される新しいCompletionStageを返す。」だけであって。すなわち次の処理が同期処理になるだけでしょうか？

またもしそうだとした場合、著者の方はsleep処理を入れたと予想できますでしょうか？まるで１秒待ってから次の処理が実行されるようなリードですが。

もしわかる方がいればよろしくお願いいたします。


CC BY-SA 4.0
2020-06-21T09:21:59.833
67862
2020-06-22T05:12:52.537
2020-06-21T09:37:05.067
40231
40231
question
java java8
CompletableFutureを使った非同期処理を理解したい


こちらの回答

  * [非同期処理において結果が思ったように出ない理由を知りたい](https://ja.stackoverflow.com/a/67221/2808)

に記載した理由と同じです。  
`Executor`を引数に取らない[`CompletableFuture.supplyAsync()`](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html#supplyAsync\(java.util.function.Supplier\))で得られたfutureは
**デーモンスレッド** で処理されます。  
ですのでメインスレッドが終了するとこのスレッドも終了します。  
が、そのタイミングで`future1`が完了しているとは限りません。  
(完了していなければ、当然、`thenApply()` 以降も実行されません。)

* * *

> thenApply自体は前の処理の完了は待たないのでしょうか？

待ちます。  
ただし、今回の場合、そもそもその「前の処理」が完了しないうちにプロセスが終了しています。

* * *

なお、このデーモンスレッドがどうこうというのは`CompletableFuture`の本質には関係がないので、とりあえずこのようなサンプルコードを試す際には([この回答](https://ja.stackoverflow.com/a/67202/2808)のように)`main`メソッドの最後に少し長めにスリープを入れる、としておけば`CompletableFuture`の学習に集中できるかと思います。  
(参照されているようなコードサンプルでは、プロセスの生存期間は`CompletableFuture`実行時間に対して十分長いことが前提になっていると思います。)


CC BY-SA 4.0
2020-06-21T15:37:09.587
67874
2020-06-22T05:12:52.537
2020-06-22T05:12:52.537
2808
2808
67862
answer