非同期処理において結果が思ったように出ない理由を知りたい


Java8,非同期処理の勉強をしています。  
以下のコードで出力結果の期待値は「200」です。

ただし、200がでたり、でなかったりします。  
**その理由を教えて下さい。**

以下のリンク先からコードは取得しました。  
<https://qiita.com/subaru44k/items/d98ad79d21abccedb20b>

出力処理である「thenAcceptAsync」が行われないことがあるとは考えづらいのですが、  
なぜ出力されない時があるのか知りたいです。

ある値を返すのはSupplierで、変換はFunctionで、それを受け取って処理をするのはConsumerで実施する。という認識です。

よろしくお願いいたします。

[code]

    package java8;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.function.Consumer;
    import java.util.function.Function;
    import java.util.function.Supplier;
    
    public class CompletableFutureTest3 {
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            Supplier<Integer> initValueSupplier = () -> 100;
            Function<Integer, Integer> multiply = value -> value * 2;
            Consumer<Integer> valueConsumer = value -> System.out.println(value);
    
            CompletableFuture<Void> future = CompletableFuture.supplyAsync(initValueSupplier)
                    .thenApplyAsync(multiply)
                    .thenAcceptAsync(valueConsumer);
        }
    
    }
    
[/code]




非同期処理の完了を待たずに`main`メソッドが終了してしまうためでしょう。

`main`メソッド終了後、プロセスの終了処理が完了する前に`System.out.println(value)`の出力が完了していれば、コンソール等に結果が出力されますが、それが間に合わないと結果が何も(場合によっては一部しか)表示されないと言うことになります。

極めてわずかなタイミングの差なので、ほんの1msecだけ`main`の完了を遅らせてやれば、確実に出力される(*)ようになるはずです。

[code]

        public static void main(String[] args) throws InterruptedException, ExecutionException {
            Supplier<Integer> initValueSupplier = () -> 100;
            Function<Integer, Integer> multiply = value -> value * 2;
            Consumer<Integer> valueConsumer = value -> System.out.println(value);
    
            CompletableFuture<Void> future = CompletableFuture.supplyAsync(initValueSupplier)
                    .thenApplyAsync(multiply)
                    .thenAcceptAsync(valueConsumer);
    
            Thread.sleep(1); //<- `main`の完了を1msec遅らせる
        }
    
[/code]

(*)「確実に出力される」のは、この問題に限っての話で、実際に非同期処理の終了を確実に完了するのを待つ場合には、yohjp
さんのコメントなども参考にしてください。




非同期処理の完了を待たずに`main`メソッドが終了してしまうためでしょう。

`main`メソッド終了後、プロセスの終了処理が完了する前に`System.out.println(value)`の出力が完了していれば、コンソール等に結果が出力されますが、それが間に合わないと結果が何も(場合によっては一部しか)表示されないと言うことになります。

極めてわずかなタイミングの差なので、ほんの1msecだけ`main`の完了を遅らせてやれば、確実に出力される(*)ようになるはずです。

[code]

        public static void main(String[] args) throws InterruptedException, ExecutionException {
            Supplier<Integer> initValueSupplier = () -> 100;
            Function<Integer, Integer> multiply = value -> value * 2;
            Consumer<Integer> valueConsumer = value -> System.out.println(value);
    
            CompletableFuture<Void> future = CompletableFuture.supplyAsync(initValueSupplier)
                    .thenApplyAsync(multiply)
                    .thenAcceptAsync(valueConsumer);
    
            Thread.sleep(1); //<- `main`の完了を1msec遅らせる
        }
    
[/code]

(*)「確実に出力される」のは、この問題に限っての話で、実際に非同期処理の終了を確実に完了するのを待つ場合には、yohjp
さんのコメントなども参考にしてください。

