CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> {
System.out.println("enter into completableFuture()");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("start to out of completableFuture()");
return "a";
});
System.out.println("do something else");
cf1.thenApply(v -> v + " b").thenAcceptAsync(v ->
System.out.println(v)
);
System.out.println("finalize...");
//注释最后一行,无法得到预期结果
//TimeUnit.SECONDS.sleep(10);
Le résultat est :
do something else
enter into completableFuture()
finalize...
start to out of completableFuture()
a b
Si vous commentez la dernière ligne du code ci-dessus, vous n'obtiendrez pas les résultats attendus.
Pourquoi devons-nous explicitement laisser le programme dormir pendant 10 secondes ?
Voir le javadoc de
CompletableFuture.supplyAsync
:Et le javadoc de
.ForkJoinPool.commonPool()
:Si vous mettez le dernier
sleep
改成ForkJoinPool.commonPool().awaitQuiescence(2, TimeUnit.SECONDS);
, vous pouvez également obtenir les résultats escomptésRecherchez : thread démon
La JVM se fermera lorsqu'il ne restera que le thread démon dans le thread. Sinon, s'il y a un thread utilisateur, la JVM ne se fermera pas.
On peut deviner que CompletableFuture.supplyAsync démarre un thread démon. En fait, CompletableFuture utilise ForkJoinPool par défaut en interne. Ce pool de threads initialise une classe de fabrique de threads :
Regardez son implémentation et créez un démon à chaque fois. Quant à savoir pourquoi le fil principal doit dormir, c'est facile à comprendre.