Futures
Futures wurden in Java 5 (2004) eingeführt. Sie sind im Grunde genommen Platzhalter für ein Ergebnis einer Operation, die noch nicht abgeschlossen ist. Sobald der Vorgang abgeschlossen ist, Future
enthält der das Ergebnis. Eine Operation kann beispielsweise eine ausführbare oder aufrufbare Instanz sein, die an einen ExecutorService gesendet wird . Der Übermittler der Operation kann das Future
Objekt verwenden, um zu überprüfen, ob die Operation fertig ist () , oder mit der blockierenden Methode get () warten, bis sie abgeschlossen ist .
Beispiel:
/**
* 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 wurden in Java 8 (2014) eingeführt. Sie sind in der Tat eine Weiterentwicklung der regulären Futures, inspiriert von Googles Listenable Futures , einem Teil der Guava- Bibliothek. Es handelt sich um Futures, mit denen Sie auch Aufgaben in einer Kette aneinanderreihen können. Sie können sie verwenden, um einem Arbeitsthread anzuweisen, "eine Aufgabe X zu erledigen, und wenn Sie fertig sind, diese andere Sache mit dem Ergebnis von X zu erledigen". Mit CompletableFutures können Sie mit dem Ergebnis der Operation etwas anfangen, ohne einen Thread zu blockieren, um auf das Ergebnis zu warten. Hier ist ein einfaches Beispiel:
/**
* 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 ist eine vollständige Bibliothek für reaktive Programmierung, die bei Netflix erstellt wurde. Auf den ersten Blick scheint es den Streams von Java 8 ähnlich zu sein . Es ist, außer es ist viel mächtiger.
Ähnlich wie bei Futures kann RxJava verwendet werden, um eine Reihe synchroner oder asynchroner Aktionen zu einer Verarbeitungspipeline zusammenzufügen. Im Gegensatz zu Futures, die zum Einmalgebrauch bestimmt sind, arbeitet RxJava mit Streams mit null oder mehr Elementen. Einschließlich nie endender Streams mit einer unendlichen Anzahl von Elementen. Es ist auch viel flexibler und leistungsfähiger dank einer unglaublich reichen Anzahl von Bedienern .
Im Gegensatz zu den Streams von Java 8 verfügt RxJava auch über einen Gegendruckmechanismus , mit dem Fälle behandelt werden können, in denen verschiedene Teile Ihrer Verarbeitungspipeline in unterschiedlichen Threads mit unterschiedlichen Raten arbeiten .
Der Nachteil von RxJava ist, dass es trotz der soliden Dokumentation aufgrund des damit verbundenen Paradigmenwechsels eine herausfordernde Bibliothek ist, etwas zu lernen. Rx-Code kann auch ein Albtraum beim Debuggen sein, insbesondere wenn mehrere Threads beteiligt sind, und noch schlimmer - wenn Gegendruck erforderlich ist.
Wenn Sie sich darauf einlassen möchten, finden Sie auf der offiziellen Website eine ganze Seite mit verschiedenen Tutorials sowie die offizielle Dokumentation und Javadoc . Sie können sich auch einige Videos wie dieses ansehen, die eine kurze Einführung in Rx geben und auch über die Unterschiede zwischen Rx und Futures sprechen.
Bonus: Java 9 Reactive Streams
Java 9s Reactive Streams aka Flow - API sind eine Reihe von Schnittstellen von verschiedenen implementierten reaktiven Strom Bibliotheken wie RxJava 2 , Akka Bäche und Vertx . Sie ermöglichen die Verbindung dieser reaktiven Bibliotheken unter Beibehaltung des wichtigen Gegendrucks.