[JAVA] Prise en main de Completable Future (First Future)

Future

Interface introduite dans Java 5. Utilisé pour modéliser les résultats futurs qui pourraient être disponibles à un moment donné. Modélisez le traitement asynchrone et fournissez une référence au résultat lorsque le traitement est terminé. Future permet au thread appelant de continuer un autre processus au lieu d'attendre le résultat. Java8 In Action

Ce qui me rend heureux d'utiliser Future

  1. Plus besoin d'attendre un traitement chronophage
  2. Plus facile à travailler que les fils à couche basse

comment utiliser

Enveloppez le processus chronophage dans l'objet Callable et passez-le à ExecutorSerice.

ExecutorService executor = Executors.newCachedThreadPool();
//Passer des tâches au pool de threads
Future<Double> future = executor.submit(new Callable<Double>() {
        public Double call() { //Effectuer le traitement dans un autre thread
            return doSomeLongComputation();
               }});
doSomethingElse();

Utilisez la méthode get de Future pour obtenir le résultat du traitement asynchrone. En utilisation réelle, vous devez intercepter plusieurs exceptions. Future.get

Double value = future.get();
Double result = future.get(1, TimeUnit.SECONDS); //Spécifiez le délai d'expiration

Éléments à prendre en compte dans le traitement asynchrone avec Future

"Si le processus encapsulé doSomeLongComputation ne renvoie jamais de résultat"

En utilisant la méthode suivante Vous pouvez être sûr que le processus asynchrone est terminé

Puis

"Lorsque le résultat de FuturedoSomeLongComputation est utilisé par un autre FuturedoSomeMoreLongComputation"

Que devrais-je faire?

Le point déroutant est qu'il existe un ordre d'exécution entre les processus asynchrones. En exécutant le deuxième futur Il est nécessaire de vérifier activement le résultat du premier futurdoSomeLongComputation. </ del>

ExecutorService executor = Executors.newCachedThreadPool();
Future<Double> future = executor.submit(new Callable<Double>() {
    public Double call() {
        return doSomeLongComputation();
    }});

//Surveiller jusqu'à ce que le traitement du premier futur soit terminé
do {
    System.out.println("in while");
} while(!future.isDone());

Future<Double> futureSecond = executor.submit(new Callable<Double>() {
    public Double call() {
        try {
            return doSomeLongMoreComputation(future.get());
        } catch (InterruptedException | ExecutionException e) {
            return 0.0;
        }
    }});

Il est possible d'écrire un processus qui a un ordre entre les processus asynchrones sans utiliser l'instruction while.

long start = System.nanoTime();
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println(String.format("before future elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
//1er avenir
Future<Double> future = executor.submit(new Callable<Double>() {
    public Double call() {
        return doSomeLongComputation();
    }});
System.out.println(String.format("after future elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
//Deuxième avenir
Future<Double> futureSecond = executor.submit(new Callable<Double>() {
    public Double call() {
        try {
            System.out.println(String.format("before future.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
            double value = future.get(); //Appelez le premier futur
            System.out.println(String.format("after future.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
            //Utilisez le résultat du traitement du premier futur
            return doSomeLongMoreComputation(value);
        } catch (InterruptedException | ExecutionException e) {
            return 0.0;
        }
    }});

try {
    System.out.println(String.format("before futureSecond.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
    //Appelez le deuxième avenir ici
    double d = futureSecond.get();
    System.out.println(String.format("after futureSecond.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
} catch (InterruptedException | ExecutionException e) {
    System.out.println(e);
}

résultat Le traitement du second futur est bloqué jusqu'à ce que le traitement du futur imbriqué soit terminé (∵ Le deuxième futur utilise le résultat du traitement du premier futur).

before future elapsed time: 3 msecs
doSomeLongComputation called 
after future elapsed time: 25 msecs
before futureSecond.get elapsed time: 26 msecs <-Commencer le deuxième avenir
before future.get elapsed time: 26 msecs <-Début du premier futur imbriqué
doSomeLongComputation: 10
after future.get elapsed time: 10027 msecs <-Fin du premier futur imbriqué
doSomeLongMoreComputation called 
doSomeLongMoreComputation: 11
after futureSecond.get elapsed time: 20029 msecs <-Fin du deuxième avenir

Ce que je veux réaliser à la fin, c'est ...

  1. Combinez deux processus asynchrones
  2. Attendez que tous les traitements effectués par le bloc Future soient terminés
  3. Attendez la fin de la tâche exécutée la plus tôt dans le bloc futur
  4. Avenir par programme complet
  5. Réagissez à l'achèvement de Future
  6. Avertir lorsque le traitement est terminé
  7. Exécutez le traitement à l'aide des résultats futurs au lieu d'attendre les résultats du traitement

celles-ci, En utilisant les fonctionnalités de ** Java8 **, Utilisez CompletableFuture si vous voulez le faire de manière déclarative.

Recommended Posts

Prise en main de Completable Future (First Future)
Premiers pas avec Ruby
Enquête future complète sur Java 8
Premiers pas avec Doma-Transactions
Premiers pas avec le traitement Doma-Annotation
Premiers pas avec Java Collection
Premiers pas avec les bases de Java
Premiers pas avec Spring Boot
Premiers pas avec les modules Ruby
Premiers pas avec Java_Chapitre 5_Exercices pratiques 5_4
[Google Cloud] Premiers pas avec Docker
Premiers pas avec Docker avec VS Code
CompletableFuture Getting Started 2 (Essayez de faire CompletableFuture)