Ostatnio przyglądałem się gorutynom Go i pomyślałem, że fajnie byłoby mieć coś podobnego w Javie. O ile szukałem, powszechnym sposobem zrównoleglenia wywołania metody jest zrobienie czegoś takiego:
final String x = "somethingelse";
new Thread(new Runnable() {
public void run() {
x.matches("something");
}
}).start();
To niezbyt eleganckie. Czy jest lepszy sposób na zrobienie tego? Potrzebowałem takiego rozwiązania w projekcie, więc zdecydowałem się zaimplementować własną klasę opakowującą wokół wywołania metody asynchronicznej.
Opublikowałem moją klasę wrapper w J-Go . Ale nie wiem, czy to dobre rozwiązanie. Użycie jest proste:
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
lub mniej szczegółowe:
Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady()) //Blocks until myRandomMethod has ended
System.out.println("Method is finished!");
Wewnętrznie używam klasy, która implementuje Runnable i wykonuję trochę pracy Reflection, aby uzyskać poprawny obiekt metody i wywołać go.
Chcę uzyskać opinię na temat mojej małej biblioteki i na temat wykonywania wywołań metod asynchronicznych w Javie. Czy to jest bezpieczne? Czy jest już prostszy sposób?
źródło
Odpowiedzi:
Właśnie odkryłem, że istnieje lepszy sposób na zrobienie tego
(Przynajmniej w Javie 8) możesz użyć wyrażenia lambda, aby skrócić je do:
Tak proste, jak utworzenie funkcji w JS!
źródło
Java 8 wprowadziła CompletableFuture dostępną w pakiecie java.util.concurrent.CompletableFuture, można użyć do wykonania połączenia asynchronicznego:
źródło
CompletableFuture
został wymieniony w innej odpowiedzi, ale ten wykorzystał całysupplyAsync(...)
łańcuch. To proste opakowanie, które idealnie pasuje do pytania.ForkJoinPool.commonPool().execute()
ma nieco mniej narzutówMożesz również rozważyć klasę
java.util.concurrent.FutureTask
.Jeśli używasz języka Java 5 lub nowszego, FutureTask jest gotową do realizacji implementacją „asynchronicznych obliczeń z możliwością anulowania”.
W
java.util.concurrent
pakiecie dostępne są jeszcze bogatsze zachowania planowania wykonywania asynchronicznego (na przykładScheduledExecutorService
), aleFutureTask
mogą mieć wszystkie wymagane funkcje.Posunąłbym się nawet do stwierdzenia, że nie jest już wskazane używanie pierwszego wzorca kodu, który podałeś jako przykład, odkąd
FutureTask
stał się dostępny. (Zakładając, że korzystasz z Java 5 lub nowszej).źródło
Nie podoba mi się pomysł wykorzystania do tego Reflection.
Nie tylko niebezpieczne, że brakuje go w niektórych refaktoryzacjach, ale można temu zaprzeczyć
SecurityManager
.FutureTask
jest dobrą opcją, podobnie jak inne opcje z pakietu java.util.concurrent.Mój ulubiony do prostych zadań:
trochę krócej niż tworzenie wątku (zadanie jest wywoływalne lub uruchamialne)
źródło
ExecutorService
instancję, aby móc dzwonić,shutdown()
kiedy trzeba.Możesz użyć składni Java8 dla CompletableFuture, w ten sposób możesz wykonać dodatkowe obliczenia asynchroniczne w oparciu o wynik wywołania funkcji asynchronicznej.
na przykład:
Więcej szczegółów można znaleźć w tym artykule
źródło
Możesz użyć
@Async
adnotacji z jcabi-Aspekty i AspectJ:Kiedy wywołujesz
save()
, nowy wątek rozpoczyna się i wykonuje swoje ciało. Twój główny wątek jest kontynuowany bez czekania na wyniksave()
.źródło
Możesz do tego użyć Future-AsyncResult.
Źródła: https://spring.io/guides/gs/async-method/
źródło
Java zapewnia również przyjemny sposób wywoływania metod asynchronicznych. w java.util.concurrent mamy ExecutorService który pomaga w tym samym. Zainicjuj swój obiekt w ten sposób -
a następnie wywołaj funkcję taką jak-
źródło
Prawdopodobnie nie jest to prawdziwe rozwiązanie, ale teraz - w Javie 8 - możesz sprawić, by ten kod wyglądał przynajmniej trochę lepiej, używając wyrażenia lambda.
Możesz to nawet zrobić w jednej linii, nadal mając ją całkiem czytelną.
źródło
Możesz użyć
AsyncFunc
od Cactoos :Zostanie wykonany w tle, a wynik będzie dostępny
get()
jako plikFuture
.źródło
Nie jest to tak naprawdę powiązane, ale gdybym miał asynchronicznie wywołać metodę, np. Mecze (), użyłbym:
Następnie do wywołania metody asynchronicznej użyłbym:
Przetestowałem to i działa. Pomyślałem, że może to pomóc innym, jeśli przyjdą po „metodę asynchroniczną”.
źródło
Jest też fajna biblioteka dla Async-Await stworzona przez EA: https://github.com/electronicarts/ea-async
Z ich pliku Readme:
Dzięki EA Async
Bez EA Async
źródło