Ricerca…


introduzione

CompletableFuture è una classe aggiunta a Java SE 8 che implementa l'interfaccia Future di Java SE 5. Oltre a supportare l'interfaccia Future, vengono aggiunti molti metodi che consentono la richiamata asincrona quando il futuro è completato.

Convertire il metodo di blocco in modo asincrono

Il seguente metodo impiegherà un secondo o due a seconda della connessione per recuperare una pagina Web e contare la lunghezza del testo. Qualunque thread lo chiamerà, bloccherà per quel periodo di tempo. Inoltre ripropone un'eccezione che è utile in seguito.

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);
    }
}

Questo lo converte in un metodo che ritornerà immediatamente spostando la chiamata del metodo di blocco su un altro thread. Per impostazione predefinita, il metodo supplyAsync eseguirà il fornitore nel pool comune. Per un metodo di blocco, probabilmente non è una buona scelta dato che si potrebbero esaurire i thread in quel pool ed è per questo che ho aggiunto il parametro di servizio opzionale.

static private ExecutorService service = Executors.newCachedThreadPool();

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

Per usare la funzione in modo asincrono si dovrebbe usare uno dei metodi che accettano una lamda da chiamare con il risultato del fornitore quando completa come ad esempio Accetta. È inoltre importante utilizzare eccezionalmente o gestire il metodo per registrare eventuali eccezioni che potrebbero essere accadute.

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;
            });

}

Semplice esempio di CompletableFuture

Nell'esempio qui sotto, il calculateShippingPrice metodo calcola il costo di trasporto, che richiede un certo tempo di elaborazione. In un esempio reale, questo sarebbe per esempio contattare un altro server che restituisce il prezzo in base al peso del prodotto e al metodo di spedizione.

Modellando questo in modo asincrono tramite CompletableFuture , possiamo continuare il lavoro differente nel metodo (cioè calcolare i costi di imballaggio).

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow