Kurze Antwort
Nein, es ist nicht mehr natürliche Callable
zu verwenden, anstatt Supplier
in CompletableFuture.supplyAsync
. Das Argument dreht sich fast ausschließlich um Semantik, also ist es in Ordnung, wenn Sie danach noch nicht überzeugt sind.
Lange Antwort
Die Callable
und Supplier
funktionalen Schnittstellen/SAM-Typen praktisch in der Funktion äquivalent sind (verzeihen Sie das Wortspiel), aber ihre Herkunft und Verwendungszweck unterscheiden.
Callable
wurde als Teil des java.util.concurrent
Pakets erstellt. Dieses Paket kam vor den großen Änderungen rund um Lambda-Ausdrücke in Java 8 und konzentrierte sich ursprünglich auf eine Reihe von Tools, mit denen Sie gleichzeitig Code schreiben konnten, ohne viel vom klassischen Modell des praktischen Multithreading abzuweichen.
Der Hauptzweck von Callable
bestand darin, eine Aktion zu abstrahieren, die in einem anderen Thread ausgeführt werden kann und die ein Ergebnis zurückgibt. Von Callable
‚s Javadoc:
Die Callable
Schnittstelle ist ähnlich Runnable
, dass beide sind konzipiert für die Klassen, deren Instanzen möglicherweise ausgeführt durch ein anderer Thread.
Supplier
wurde als Teil des java.util.function
Paket erstellt. Dieses Paket war ein integraler Bestandteil der oben genannten Änderungen in Java 8. Es bietet allgemeine funktionale Typen, auf die Lambda-Ausdrücke und Methodenreferenzen abzielen können.
Ein solcher Typ ist eine Funktion ohne Parameter, die ein Ergebnis liefert (d. H. Eine Funktion, die einen Typ oder eine Supplier
-Funktion liefert).
Warum also Supplier
und nicht Callable
?
CompletableFuture
ist Teil Ergänzungen das java.util.concurrent
Paket, das 8 durch die vorgenannten Änderungen in Java inspiriert wurden und dass damit der Entwickler seinen Code in einer funktionalen, implizit parallelizable Weise zu konstruieren, statt explizit Umgang mit Parallelität innerhalb dieser Gruppe.
Ihre Methode benötigt einen Weg, um ein Ergebnis eines bestimmten Typs zu liefern und ist mehr an diesem Ergebnis interessiert, und nicht an der Aktion, die unternommen wird, um dieses Ergebnis zu erreichen. Es kümmert sich auch nicht unbedingt um außergewöhnliche Fertigstellung (siehe auch die Was ist mit dem ... Absatz unten).
Dennoch, wenn Runnable
für No-Parameter verwendet wird, soll kein Ergebnis funktionale Schnittstelle, nicht Callable
für No-Parameter verwendet wird, funktionale Schnittstelle Single-Ergebnis?
Nicht unbedingt.
Eine Abstraktion für eine Funktion, die keinen Parameter hat und kein Ergebnis zurückgibt (und daher vollständig durch Nebeneffekte für den äußeren Kontext funktioniert), wurde in java.util.function
nicht berücksichtigt. Dies bedeutet, dass (etwas störend) Runnable
überall dort eingesetzt wird, wo eine solche funktionale Schnittstelle benötigt wird.
Was ist mit der geprüften Exception
, die von Callable.call()
geworfen werden kann?
Es ist ein kleines Zeichen des beabsichtigten semantischen Unterschieds zwischen Callable
und Supplier
.
Eine Callable
ist eine Aktion, die in einem anderen Thread ausgeführt werden kann und die es ermöglicht, ihre Nebenwirkungen als Ergebnis ihrer Ausführung zu überprüfen. Wenn alles gut geht, erhalten Sie ein Ergebnis eines bestimmten Typs, aber da beim Ausführen einiger Aktionen (insbesondere im Multithread-Kontext) Ausnahmesituationen auftreten können, sollten Sie auch solche Ausnahmesituationen definieren und behandeln.
Eine Supplier
Auf der anderen Seite ist eine Funktion, auf die Sie für die Bereitstellung von Objekten eines bestimmten Typs angewiesen sind. Außergewöhnliche Situationen sollten nicht unbedingt Ihre Verantwortung als direkter Verbraucher der Supplier
sein. Dies ist so, weil:
- ... funktionale Schnittstellen sind für die Definition einer bestimmten Stufe in einem mehrstufigen Verfahren häufig verwendet für die Erstellung oder mutiert Daten und Handhabung
Exception
s kann eine separate Bühne sein, falls Sie kümmern
- ... explizit die ausdrucks~~POS=TRUNC von funktionalen Schnittstellen, Lambda-Ausdrücke und Verfahren deutlich reduziert s Handhabung
Exception
verweist
Weil sie von C# einfach anders sein mußte, die 'Aktion allgemein genannt wird <>' und ' Func <> 'Schnittstellen, die den gleichen Job machen, aber ohne den Programmierer zu verwirren. Und so wuchsen sie funktionale Schnittstellen für Methoden mit den gleichen Signaturen, aber unterschiedlichen Namen. Sie dachten wahrscheinlich, dass es dem Programmierer helfen würde, indem sie ihm ein mentales Modell zur Verfügung stellten, aber es ist nicht so: Es ist nur eine kleine PITA. – davidbak