Futures
Futures zostały wprowadzone w Javie 5 (2004). Są to po prostu symbole zastępcze dla wyniku operacji, która jeszcze się nie zakończyła. Po zakończeniu operacji Future
będzie zawierać ten wynik. Na przykład operacją może być instancja Runnable lub Callable, która jest przesyłana do usługi ExecutorService . Podmiot wysyłający operację może użyć Future
obiektu do sprawdzenia, czy operacja toDone () , lub poczekać, aż zakończy się przy użyciu blokującej metody get () .
Przykład:
/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
return 1;
}
}
public static void main(String[] args) throws Exception{
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<Integer> f = exec.submit(new MyCallable());
System.out.println(f.isDone()); //False
System.out.println(f.get()); //Waits until the task is done, then prints 1
}
CompletableFutures
CompletableFutures zostały wprowadzone w Javie 8 (2014). W rzeczywistości są one ewolucją zwykłych kontraktów futures, zainspirowanych Google Playable Futures , częścią biblioteki Guava . Są to kontrakty futures, które pozwalają również łączyć zadania w łańcuch. Możesz ich użyć, aby powiedzieć niektórym wątkom roboczym, że „idź zrób jakieś zadanie X, a kiedy skończysz, zrób to samo, używając wyniku X”. Korzystając z CompletableFutures, możesz zrobić coś z wynikiem operacji bez faktycznego blokowania wątku w oczekiwaniu na wynik. Oto prosty przykład:
/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {
@Override
public Integer get() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//Do nothing
}
return 1;
}
}
/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {
@Override
public Integer apply(Integer x) {
return x + 1;
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newSingleThreadExecutor();
CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
System.out.println(f.isDone()); // False
CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}
RxJava
RxJava to cała biblioteka do programowania reaktywnego stworzona w Netflix. Na pierwszy rzut oka będzie wyglądać podobnie do strumieni Java 8 . Jest, z wyjątkiem tego, że jest znacznie potężniejszy.
Podobnie jak Futures, RxJava może być używany do łączenia ze sobą szeregu akcji synchronicznych lub asynchronicznych w celu utworzenia potoku przetwarzania. W przeciwieństwie do kontraktów futures, które są jednorazowego użytku, RxJava działa na strumieniach zerowych lub więcej przedmiotów. W tym niekończące się strumienie z nieskończoną liczbą przedmiotów. Jest także znacznie bardziej elastyczny i wydajny dzięki niewiarygodnie bogatemu zestawowi operatorów .
W przeciwieństwie do strumieni Java 8, RxJava ma również mechanizm ciśnienia wstecznego , który pozwala mu obsługiwać przypadki, w których różne części twojego potoku przetwarzania działają w różnych wątkach, z różnymi prędkościami .
Minusem RxJava jest to, że pomimo solidnej dokumentacji jest to trudna biblioteka do nauczenia się z powodu zmiany paradygmatu. Kod Rx może być również koszmarem do debugowania, szczególnie jeśli w grę wchodzi wiele wątków, a nawet gorzej - jeśli potrzebne jest ciśnienie wsteczne.
Jeśli chcesz się tym zająć, na oficjalnej stronie znajduje się cała strona z różnymi samouczkami, a także oficjalna dokumentacja i Javadoc . Możesz także rzucić okiem na niektóre filmy, takie jak ten, który zawiera krótkie wprowadzenie do Rx, a także mówi o różnicach między Rx a Futures.
Premia: Reaktywne strumienie Java 9
Reaktywne strumienie Java 9, zwane Flow API, to zestaw interfejsów implementowanych przez różne biblioteki strumieni reaktywnych, takie jak RxJava 2 , Akka Streams i Vertx . Pozwalają one na połączenie tych reaktywnych bibliotek, zachowując jednocześnie wszystkie ważne przeciwciśnienia.