2017-02-28 25 views
8

Jestem nowym użytkownikiem funkcji współbieżności Java 8, takich jak CompletableFuture i mam nadzieję, że pomożesz w rozpoczęciu korzystania z poniższego przykładu użycia.Java 8 - Połącz asynchroniczne połączenia równolegle i połącz ich wyniki.

Istnieje usługa o nazwie TimeConsumingServices, która zapewnia czasochłonne operacje, które chciałbym uruchomić równolegle, ponieważ wszystkie z nich są niezależne.

interface TimeConsumingService { 

    default String hello(String name) { 
    System.out.println(System.currentTimeMillis() + " > hello " + name); 
    return "Hello " + name; 
    } 
    default String planet(String name) { 
    System.out.println(System.currentTimeMillis() + " > planet " + name); 
    return "Planet: " + name; 
    } 
    default String echo(String name) { 
    System.out.println(System.currentTimeMillis() + " > echo " + name); 
    return name; 
    } 

    default byte[] convert(String hello, String planet, String echo) { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(hello); 
    sb.append(planet); 
    sb.append(echo); 
    return sb.toString().getBytes(); 
    } 
} 

Do tej pory zaimplementowałem następujący przykład i udało mi się połączyć wszystkie trzy metody obsługi równolegle.

public class Runner implements TimeConsumingService { 

    public static void main(String[] args) { 
    new Runner().doStuffAsync(); 
    } 

    public void doStuffAsync() { 
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> this.hello("Friend")); 
    CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> this.planet("Earth")); 
    CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> this.echo("Where is my echo?")); 

    CompletableFuture.allOf(future1, future2, future3).join(); 
    } 
} 

Czy istnieje sposób, aby zbierać wartości zwracanych każdego zgłoszenia serwisowego i wywołać metodę byte[]‘ convert(String, String, String)?

Odpowiedz

8

Aby połączyć wynik po powróciły im wszystko może zrobić coś takiego

CompletableFuture<byte[]> byteFuture = CompletableFuture.allOf(cf1, cf2, cf3) 
        .thenApplyAsync(aVoid -> convert(cf1.join(), cf2.join(), cf3.join())); 
byte[] bytes = byteFuture.join(); 

To będzie przebiegać wszystkie wasze kontrakty, czekać, aż wszystkie się zakończą, a jak tylko skończą, zadzwonią pod numer convert Metoda, o której wspomniałeś.

2

Po przystąpić można po prostu get() wartości od future1 jak:

String s1 = future1.get() 

i tak dalej

+0

Ale jeśli zadzwonię 'future1.get(); future2.get(); future3.get(); 'nie są wywoływane równolegle, prawda? – saw303

+2

Wywołując metodę future1.get(), otrzymujemy już obliczony wynik. –

+1

Tak uzyskiwanie wyników nie jest wywoływane równolegle, ale wszystkie metody będą obliczane asynchronicznie. Możesz to sprawdzić dodając 'TimeUnit.seconds (2) .sleep()'; po połączeniu metoda. Zobaczysz, że 'System.out.println' został wywołany przed snem. – user2377971

0

Można łączyć je za pomocą thenCombine() metodę, jeśli jest tylko 3 futures, aby zakończyć:

final CompletableFuture<byte[]> byteFuture = future1.thenCombine(future2, (t, u) -> { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(t); 
    sb.append(u); 
    return sb.toString(); 
}).thenCombine(future3, (t, u) -> { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(t); 
    sb.append(u); 
    return sb.toString(); 
}).thenApply(s -> s.getBytes()); 

try { 
    final byte[] get = byteFuture.get(); 
} catch (InterruptedException | ExecutionException ex) { 
}