Ich habe mir in letzter Zeit Go's Goroutinen angesehen und dachte, es wäre schön, etwas Ähnliches in Java zu haben. Soweit ich gesucht habe, besteht die übliche Methode zur Parallelisierung eines Methodenaufrufs darin, Folgendes zu tun:
final String x = "somethingelse";
new Thread(new Runnable() {
public void run() {
x.matches("something");
}
}).start();
Das ist nicht sehr elegant. Gibt es einen besseren Weg, dies zu tun? Ich brauchte eine solche Lösung in einem Projekt und beschloss, meine eigene Wrapper-Klasse um einen asynchronen Methodenaufruf herum zu implementieren.
Ich habe meine Wrapper-Klasse in J-Go veröffentlicht . Aber ich weiß nicht, ob es eine gute Lösung ist. Die Verwendung ist einfach:
SampleClass obj = ...
FutureResult<Integer> res = ...
Go go = new Go(obj);
go.callLater(res, "intReturningMethod", 10); //10 is a Integer method parameter
//... Do something else
//...
System.out.println("Result: "+res.get()); //Blocks until intReturningMethod returns
oder weniger ausführlich:
Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady()) //Blocks until myRandomMethod has ended
System.out.println("Method is finished!");
Intern verwende ich eine Klasse, die Runnable implementiert und einige Reflection-Arbeiten ausführt, um das richtige Methodenobjekt abzurufen und aufzurufen.
Ich möchte eine Meinung zu meiner winzigen Bibliothek und zum Thema asynchrone Methodenaufrufe wie diese in Java. Ist es sicher? Gibt es schon einen einfacheren Weg?
quelle
Antworten:
Ich habe gerade herausgefunden, dass es einen saubereren Weg gibt, dies zu tun
(Zumindest in Java 8) können Sie einen Lambda-Ausdruck verwenden, um ihn zu verkürzen:
So einfach wie das Erstellen einer Funktion in JS!
quelle
Java 8 führte CompletableFuture ein, das im Paket java.util.concurrent.CompletableFuture verfügbar ist und verwendet werden kann, um einen asynchronen Aufruf durchzuführen:
quelle
CompletableFuture
wurde in einer anderen Antwort erwähnt, aber diese benutzte die ganzesupplyAsync(...)
Kette. Dies ist ein einfacher Wrapper, der perfekt zur Frage passt.ForkJoinPool.commonPool().execute()
hat etwas weniger OverheadVielleicht möchten Sie auch die Klasse berücksichtigen
java.util.concurrent.FutureTask
.Wenn Sie Java 5 oder höher verwenden, FutureTask eine schlüsselfertige Implementierung von "Eine stornierbare asynchrone Berechnung".
Das
java.util.concurrent
Paket bietet (z. B.ScheduledExecutorService
) noch umfassendere Verhaltensweisen bei der asynchronen AusführungsplanungFutureTask
möglicherweise über alle erforderlichen Funktionen.Ich würde sogar so weit gehen zu sagen, dass es nicht mehr ratsam ist, das erste Codemuster zu verwenden, das Sie als Beispiel angegeben haben, seit es
FutureTask
verfügbar ist. (Angenommen, Sie verwenden Java 5 oder höher.)quelle
Ich mag die Idee, Reflection dafür zu verwenden, nicht.
Es ist nicht nur gefährlich, es bei einem Refactoring zu verpassen, sondern kann auch von abgelehnt werden
SecurityManager
.FutureTask
ist eine gute Option wie die anderen Optionen aus dem Paket java.util.concurrent.Mein Favorit für einfache Aufgaben:
etwas kürzer als das Erstellen eines Threads (Aufgabe ist Callable oder Runnable)
quelle
ExecutorService
Instanz im Auge zu behalten , damit Sie anrufen können,shutdown()
wenn Sie müssen.Sie können die Java8-Syntax für CompletableFuture verwenden. Auf diese Weise können Sie zusätzliche asynchrone Berechnungen basierend auf dem Ergebnis des Aufrufs einer asynchronen Funktion durchführen.
beispielsweise:
Weitere Details finden Sie in diesem Artikel
quelle
Sie können
@Async
Anmerkungen aus jcabi-Aspekten und AspectJ verwenden:Wenn Sie aufrufen
save()
, startet ein neuer Thread und führt seinen Body aus. Ihr Haupt-Thread wird fortgesetzt, ohne auf das Ergebnis von zu wartensave()
.quelle
Hierfür können Sie Future-AsyncResult verwenden.
Referenz: https://spring.io/guides/gs/async-method/
quelle
Java bietet auch eine gute Möglichkeit, asynchrone Methoden aufzurufen. In java.util.concurrent haben wir ExecutorService , der dabei hilft, dasselbe zu tun. Initialisieren Sie Ihr Objekt so -
und rufen Sie dann die Funktion like-
quelle
Es ist wahrscheinlich keine echte Lösung, aber jetzt - in Java 8 - können Sie diesen Code mit dem Lambda-Ausdruck zumindest ein wenig besser aussehen lassen.
Und Sie könnten dies sogar in einer Zeile tun, wobei es immer noch ziemlich lesbar ist.
quelle
Sie können
AsyncFunc
von Cactoos verwenden :Es wird im Hintergrund ausgeführt werden , und das Ergebnis wird in verfügbar sein
get()
alsFuture
.quelle
Dies hängt nicht wirklich zusammen, aber wenn ich eine Methode asynchron aufrufen würde, z. B. match (), würde ich Folgendes verwenden:
Um dann die asynchrone Methode aufzurufen, würde ich verwenden:
Ich habe das getestet und es funktioniert. Ich dachte nur, es könnte anderen helfen, wenn sie nur für die "asynchrone Methode" kommen.
quelle
Es gibt auch eine schöne Bibliothek für Async-Await, die von EA erstellt wurde: https://github.com/electronicarts/ea-async
Aus ihrer Readme:
Mit EA Async
Ohne EA Async
quelle