CompletableFuture supplyAsync
Ich habe gerade erst begonnen zu erkunden einige concurrency-features von Java 8. Eine Sache verwirrt mich ein bisschen ist diese zwei statischen Methoden:
CompletableFuture<Void> runAsync(Runnable runnable)
CompletableFuture<U> supplyAsync(Supplier<U> supplier)
Tun, wer weiß, warum Sie wählen, um Schnittstelle zu verwenden, Lieferanten? Ist es nicht natürlicher zu bedienen Callable, das ist die Analogie von Runnable, die einen Wert zurückgibt? Ist, weil der Lieferant nicht eine Ausnahme, die nicht behandelt werden?
- Denn Sie musste einfach anders sein als C#, die generisch benannten
Action<>
undFunc<>
- Schnittstellen, die denselben job erledigen, aber ohne verwirrend die Programmierer. Und so werden Sie vermehrt funktionale Schnittstellen, die für Methoden mit gleichen Signaturen, aber unterschiedliche Namen. Wahrscheinlich dachte Sie, es würde helfen, den Programmierer, indem Sie ihm ein mentales Modell, mit zu arbeiten, aber es funktioniert nicht: Es ist nur eine kleine PITA.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Kurze Antwort
Nein, es ist nicht mehr selbstverständlich, zu verwenden
Callable
stattSupplier
imCompletableFuture.supplyAsync
. Das argument wird fast ausschließlich über die Semantik, also ist es OK, wenn du dich immer noch nicht überzeugt danach.Lange Antwort
Den
Callable
undSupplier
funktionalen Schnittstellen/SAM-Typen sind praktisch gleichwertig in Funktion (verzeihen Sie das Wortspiel), aber Ihre Herkunft und Verwendungszweck unterscheiden.Callable
wurde als Teil derjava.util.concurrent
Paket. Das Paket kam vor der riesigen Veränderungen rund um lambda-Ausdrücke in Java 8 und ursprünglich konzentrierte sich auf eine Reihe von tools, die Ihnen geholfen gleichzeitige schreiben von code, ohne viel abweichend von dem klassischen Modell der hands-on-multithreading.Den Hauptzweck der
Callable
war zu Abstrakt, eine Aktion, die ausgeführt werden können in einem anderen thread und gibt ein Ergebnis zurück. VonCallable
's Javadoc:Supplier
wurde als Teil derjava.util.function
Paket. Das Paket kam als integraler Bestandteil des oben beschriebenen änderungen in Java 8. Es bietet gemeinsame funktionale Typen, die ausgerichtet werden können durch die lambda expressions und method references.Einer solchen Art ist eine Funktion ohne Parameter, die ein Ergebnis liefert (d.h. eine Funktion, die Vorräte irgendein Typ oder eine
Supplier
- Funktion).Warum also
Supplier
und nichtCallable
?CompletableFuture
ist Teil der Ergänzungen zumjava.util.concurrent
- Paket, die inspiriert wurden durch die oben beschriebenen änderungen in Java 8 und ermöglicht, dass der Entwickler baut seinen code in einem funktionalen, implizit parallelisierbare Art und Weise, anstatt explizit Umgang mit Parallelität innerhalb es.Seine
supplyAsync
- Methode muss ein Ergebnis eines bestimmten Typs und seiner mehr daran interessiert, dieses Ergebnis, und nicht in die Aktion, um dieses Ergebnis zu erreichen. Es ist auch nicht unbedingt kümmern außergewöhnlichen Abschluss (siehe auch die Was über die... Absatz unten).Noch, wenn
Runnable
verwendet wird, für die kein Parameter, kein Ergebnis funktionale Oberfläche, sollte nichtCallable
verwendet werden, für die keine Parameter, single-result funktionale Schnittstelle?Nicht unbedingt.
Abstraktion für eine Funktion, die keine parameter haben und kein Ergebnis zurückliefert (und arbeitet daher vollständig über die Nebenwirkungen auf, die außerhalb Rahmen) war nicht enthalten, in
java.util.function
. Dies bedeutet, dass (etwas störend)Runnable
wird überall dort eingesetzt, wo eine solche funktionale Schnittstelle benötigt wird.Was ist mit dem überprüft
Exception
ausgelöst werden kannCallable.call()
?Es ist ein kleines Zeichen der beabsichtigten semantischen Unterschied zwischen
Callable
undSupplier
.Einen
Callable
ist eine Aktion, die ausgeführt werden können, die in einem anderen thread, und das können Sie überprüfen die Nebenwirkungen, die als Ergebnis Ihrer Ausführung. Wenn alles gut geht, bekommen Sie ein Ergebnis eines bestimmten Typs, aber da außergewöhnliche Situationen auftreten können, beim ausführen von einigen Aktionen (vor allem in Multithread-Kontext), können Sie auch wollen, zu definieren und zu behandeln, solche außergewöhnlichen Situationen.Einen
Supplier
auf der anderen Seite ist eine Funktion, auf die Sie sich verlassen für die Versorgung der Objekte eines Typs. Außergewöhnliche Situationen sollten nicht unbedingt gemacht werden, Ihre Verantwortung als direkten Verbraucher von derSupplier
. Dies ist so, weil:Exception
s kann eine separate Phase, in Fall, dass Sie PflegeException
s reduziert deutlich die Ausdruckskraft der funktionale interfaces, lambda-Ausdrücke und-Methode Referenzencall()
vsget()
) war schlecht durchdacht und führt zu viel ärger. Zwei sind insbesondere: versucht sich zu erinnern, was das verflixte Methode Sie aufrufen müssen, und dann nicht leicht in der Lage zu senden, ein Zulieferer habe Sie eine Methode benötigen, Aufrufbar, etc. etc. Die beabsichtigte "Semantik", die Sie beschreiben, sind alle in Worte und haben nichts zu tun mit etwas, was der compiler durchsetzen würde und sind schlecht beschrieben oder nicht beschrieben wird, überhaupt in den Java-docs. C# hast es besser.