Maison > Questions et réponses > le corps du texte
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 ?
某草草2017-06-15 09:24:15
Voir le javadoc de CompletableFuture.supplyAsync
:
Renvoie un nouveau CompletableFuture qui est complété de manière asynchrone par une tâche exécutée dans le
ForkJoinPool.commonPool()
avec la valeur obtenue en appelant le fournisseur donné.
Et le javadoc de ForkJoinPool.commonPool()
:
.Renvoie l'instance de pool commun. Ce pool est construit de manière statique ; son état d'exécution n'est pas affecté par les tentatives d'arrêt ou d'arrêt. Cependant, ce pool et tout traitement en cours sont automatiquement terminés lors du programme
System.exit
. Any program that relies on asynchronous task processing to complete before program termination should invokecommonPool().awaitQuiescence
, avant sa sortie.
Si vous mettez le dernier sleep
改成ForkJoinPool.commonPool().awaitQuiescence(2, TimeUnit.SECONDS);
, vous pouvez également obtenir les résultats escomptés
某草草2017-06-15 09:24:15
Recherchez : 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 :
defaultForkJoinWorkerThreadFactory = new DefaultForkJoinWorkerThreadFactory();
Regardez son implémentation et créez un démon à chaque fois. Quant à savoir pourquoi le fil principal doit dormir, c'est facile à comprendre.