Recherche…


Introduction

CompletableFuture est une classe ajoutée à Java SE 8 qui implémente l'interface Future de Java SE 5. Outre la prise en charge de l'interface Future, elle ajoute de nombreuses méthodes permettant un rappel asynchrone lorsque le futur est terminé.

Convertir la méthode de blocage en asynchrone

La méthode suivante prendra une seconde ou deux selon votre connexion pour récupérer une page Web et compter la longueur du texte. Quel que soit le thread qui l'appelle, il sera bloqué pour cette période. En outre, il relance une exception utile par la suite.

public static long blockingGetWebPageLength(String urlString) {
    try (BufferedReader br = new BufferedReader(new InputStreamReader(new URL(urlString).openConnection().getInputStream()))) {
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        return sb.toString().length();
    } catch (IOException ex) {
        throw new RuntimeException(ex);
    }
}

Cela le convertit en une méthode qui retournera immédiatement en déplaçant l'appel de la méthode de blocage vers un autre thread. Par défaut, la méthode supplyAsync exécutera le fournisseur sur le pool commun. Pour une méthode de blocage, ce n'est probablement pas un bon choix car on peut épuiser les threads de ce pool, c'est pourquoi j'ai ajouté le paramètre de service facultatif.

static private ExecutorService service = Executors.newCachedThreadPool();

static public CompletableFuture<Long> asyncGetWebPageLength(String url) {
    return CompletableFuture.supplyAsync(() -> blockingGetWebPageLength(url), service);
}

Pour utiliser la fonction de manière asynchrone, il faut utiliser les méthodes qui acceptent l’appel d’une lamda avec le résultat du fournisseur lorsque celui-ci se termine comme thenAccept. Il est également important d'utiliser exceptionnellement ou de gérer la méthode pour consigner les éventuelles exceptions.

public static void main(String[] args) {

    asyncGetWebPageLength("https://stackoverflow.com/")
            .thenAccept(l -> {
                System.out.println("Stack Overflow returned " + l);
            })
            .exceptionally((Throwable throwable) -> {
                Logger.getLogger("myclass").log(Level.SEVERE, "", throwable);
                return null;
            });

}

Exemple simple de CompletableFuture

Dans l'exemple ci - dessous, la calculateShippingPrice méthode calcule les coûts d'expédition, ce qui prend un certain temps de traitement. Dans un exemple concret, il s'agirait par exemple de contacter un autre serveur qui renvoie le prix en fonction du poids du produit et du mode de livraison.

En modélisant cela de manière asynchrone via CompletableFuture , nous pouvons continuer différents travaux dans la méthode (c.-à-d. Calculer les coûts d'emballage).

public static void main(String[] args) {
    int price = 15; // Let's keep it simple and work with whole number prices here
    int weightInGrams = 900;
    
    calculateShippingPrice(weightInGrams) // Here, we get the future
        .thenAccept(shippingPrice -> { // And then immediately work on it!
            // This fluent style is very useful for keeping it concise
            System.out.println("Your total price is: " + (price + shippingPrice));
        });
    System.out.println("Please stand by. We are calculating your total price.");
}


public static CompletableFuture<Integer> calculateShippingPrice(int weightInGrams) {
    return CompletableFuture.supplyAsync(() -> { 
        // supplyAsync is a factory method that turns a given 
        // Supplier<U> into a CompletableFuture<U>

        // Let's just say each 200 grams is a new dollar on your shipping costs
        int shippingCosts = weightInGrams / 200;
        
        try {
            Thread.sleep(2000L); // Now let's simulate some waiting time...
        } catch(InterruptedException e) { /* We can safely ignore that */ }

        return shippingCosts; // And send the costs back!
    });
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow