Sök…


Introduktion

CompletableFuture är en klass som läggs till Java SE 8 som implementerar Future-gränssnittet från Java SE 5. Förutom att stödja Future-gränssnittet lägger det till många metoder som tillåter asynkron återuppringning när framtiden är klar.

Konvertera blockeringsmetod till asynkron

Följande metod tar en sekund eller två beroende på din anslutning för att hämta en webbsida och räkna textlängden. Oavsett vilken tråd som kallas kommer den att blockeras under den perioden. Dessutom återkallar det ett undantag som är användbart senare.

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

Detta konverterar det till en metod som omedelbart kommer att återgå genom att flytta blockeringsmetodens samtal till en annan tråd. Som standard kör metoden supplyAsync leverantören i den gemensamma poolen. För en blockeringsmetod är detta förmodligen inte ett bra val eftersom man kan ta ut trådarna i den poolen och det är därför jag har lagt till den valfria serviceparametern.

static private ExecutorService service = Executors.newCachedThreadPool();

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

För att använda funktionen på asynkron sätt bör man använda på de metoder som accepterar en lamda som ska kallas med resultatet av leverantören när den är klar så som dåAccept. Det är också viktigt att använda exceptionellt eller hantera metod för att logga alla undantag som kan ha hänt.

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

}

Enkelt exempel på CompletableFuture

I exemplet nedan calculateShippingPrice metoden calculShippingPrice fraktkostnader, vilket tar lite behandlingstid. I ett verkligt exempel skulle detta t.ex. vara att kontakta en annan server som returnerar priset baserat på produktens vikt och leveransmetoden.

Genom att modellera detta på ett asynkiskt sätt via CompletableFuture , kan vi fortsätta olika arbeten i metoden (dvs. beräkna förpackningskostnader).

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow