W kotlinx.coroutines
bibliotece możesz uruchomić nowy program, używając launch
(zjoin
) lub async
(z await
). Jaka jest różnica między nimi?
źródło
W kotlinx.coroutines
bibliotece możesz uruchomić nowy program, używając launch
(zjoin
) lub async
(z await
). Jaka jest różnica między nimi?
launch
służy do odpalania i zapomnienia programu . To jak rozpoczęcie nowego wątku. Jeśli kod wewnątrz launch
kończy się z wyjątkiem, jest traktowany jak nieprzechwycony wyjątek w wątku - zwykle jest drukowany na stderr w aplikacjach JVM zaplecza i powoduje awarię aplikacji na Androida. join
służy do oczekiwania na zakończenie uruchomionego programu i nie propaguje swojego wyjątku. Jednak uszkodzony program podrzędny anuluje również swojego rodzica z odpowiednim wyjątkiem.
async
służy do uruchamiania programu, który oblicza jakiś wynik . Wynik jest reprezentowany przez instancję Deferred
i należyawait
na niej użyć . Nieprzechwycony wyjątek w async
kodzie jest przechowywany w wynikowym Deferred
i nie jest dostarczany nigdzie indziej, zostanie po cichu usunięty, chyba że zostanie przetworzony. NIE WOLNO zapominać o programie, który zacząłeś z async .
Uważam, że ten przewodnik https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md jest przydatny. Zacytuję najważniejsze części
🦄 coroutine
Możesz więc myśleć o programie coroutine jako o czymś, co zarządza wątkiem w bardzo wydajny sposób.
🐤 uruchomienie
Więc
launch
uruchamia wątek w tle, robi coś i natychmiast zwraca token jakoJob
. Możesz wywołaćjoin
to,Job
aby zablokować dolaunch
zakończenia tego wątku🦆 async
Więc
async
uruchamia wątek w tle, robi coś i natychmiast zwraca token jakoDeferred
.Tak
Deferred
naprawdę jestJob
. Zobacz https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html🦋 asynchronizacja jest domyślnie gorsza
źródło
launch
iasync
są używane do uruchamiania nowych programów. Ale wykonują je w inny sposób.Chciałbym pokazać bardzo podstawowy przykład, który pomoże ci bardzo łatwo zrozumieć różnicę
W tym przykładzie mój kod pobiera 3 dane po kliknięciu
btnCount
przycisku i wyświetlapgBar
pasek postępu do zakończenia pobierania. Istnieją 3suspend
funkcjedownloadTask1()
,downloadTask2()
idownloadTask3()
które pobiera dane. Aby to zasymulować, użyłemdelay()
w tych funkcjach. Funkcje te czeka5 seconds
,8 seconds
i5 seconds
odpowiednio.Tak jak używaliśmy
launch
do uruchamiania tych funkcji wstrzymania,launch
będzie wykonywać je sekwencyjnie (jedna po drugiej) . Oznacza to,downloadTask2()
że zacznie się podownloadTask1()
zakończeniu idownloadTask3()
zacznie się dopiero podownloadTask2()
zakończeniu.Podobnie jak w przypadku zrzutu ekranu wyjściowego
Toast
, całkowity czas wykonania wszystkich 3 pobrań wyniósłby 5 sekund + 8 sekund + 5 sekund = 18 sekund zlaunch
Jak widzieliśmy,
launch
powoduje to wykonaniesequentially
wszystkich 3 zadań. Nadszedł czas na wykonanie wszystkich zadań18 seconds
.Jeśli te zadania są niezależne i nie wymagają wyniku obliczeń innego zadania, możemy je uruchomić
concurrently
. Uruchamiałyby się w tym samym czasie i działały równolegle w tle. Można to zrobić za pomocąasync
.async
zwraca instancjęDeffered<T>
typu, gdzieT
jest typem danych zwracanych przez naszą funkcję zawieszenia. Na przykład,downloadTask1()
zwróci,Deferred<String>
ponieważ String jest zwracanym typem funkcjidownloadTask2()
zwróci,Deferred<Int>
ponieważ Int jest zwracanym typem funkcjidownloadTask3()
zwróci,Deferred<Float>
ponieważ Float jest zwracanym typem funkcjiMożemy użyć zwracanego obiektu from
async
typu,Deferred<T>
aby otrzymać zwróconą wartość wT
typie. Można to zrobićawait()
telefonicznie. Sprawdź na przykład poniższy kodW ten sposób uruchomiliśmy wszystkie 3 zadania jednocześnie. Tak więc mój całkowity czas wykonania do ukończenia byłby tylko tym, na
8 seconds
który jest czas,downloadTask2()
ponieważ jest to największe ze wszystkich trzech zadań. Możesz to zobaczyć na poniższym zrzucie ekranu wToast message
źródło
launch
jest dla kolejnych miłośników, natomiastasync
na równoczesnąlaunch
iasync
rozpoczną nowe programy. Porównujesz pojedynczy program bez dzieci z jednym programem z trojgiem dzieci. Możesz zamienić każde zasync
wywołań nalaunch
i absolutnie nic by się nie zmieniło w odniesieniu do współbieżności.oba programy budujące programy, a mianowicie uruchamianie i asynchronizacja, są w zasadzie lambdami z odbiornikiem typu CoroutineScope, co oznacza, że ich wewnętrzny blok jest kompilowany jako funkcja wstrzymania, dlatego oba działają w trybie asynchronicznym ORAZ obaj będą wykonywać swój blok sekwencyjnie.
Różnica między uruchomieniem a asynchronizacją polega na tym, że umożliwiają one dwie różne możliwości. Kreator uruchamiania zwraca zadanie, jednak funkcja async zwróci obiekt odroczony. Możesz użyć uruchomienia, aby wykonać blok, którego nie oczekujesz od niego żadnej zwróconej wartości, tj. Zapisanie do bazy danych lub zapisanie pliku lub przetworzenie czegoś, co w zasadzie wywołało efekt uboczny. Z drugiej strony asynchronizacja, która zwraca Deferred, tak jak powiedziałem wcześniej, zwraca użyteczną wartość z wykonania swojego bloku, obiektu, który opakowuje twoje dane, więc możesz go użyć głównie do jego wyniku, ale być może również do efektu ubocznego. Uwaga: możesz usunąć deferred i uzyskać jego wartość za pomocą funkcji await, która będzie blokować wykonywanie twoich instrukcji do momentu zwrócenia wartości lub wyrzucenia wyjątków!
oba narzędzia do tworzenia programów (uruchamianie i asynchronizacja) można anulować.
cokolwiek więcej ?: tak z uruchomieniem, jeśli wyjątek zostanie zgłoszony w jego bloku, program zostanie automatycznie anulowany, a wyjątki zostaną dostarczone. Z drugiej strony, jeśli dzieje się tak w przypadku asynchronizacji, wyjątek nie jest dalej propagowany i powinien zostać przechwycony / obsłużony w zwróconym obiekcie Deferred.
więcej na temat coroutines https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html https://www.codementor.io/blog/kotlin-coroutines-6n53p8cbn1
źródło
uruchomienie zwraca zadanie
async zwraca wynik (zadanie odroczone)
uruchomienie z łączeniem służy do czekania, aż zadanie zostanie zakończone. po prostu zawiesza wywołanie funkcji join (), pozostawiając bieżący wątek wolny do wykonywania w międzyczasie innych prac (takich jak wykonywanie innego programu).
async służy do obliczania niektórych wyników. Tworzy coroutine i zwraca jego przyszły wynik jako implementację Deferred. Uruchomiony program jest anulowany, gdy wynikowe odroczenie zostanie anulowane.
Rozważ metodę asynchroniczną, która zwraca wartość ciągu. Jeśli metoda async jest używana bez await, zwróci ona ciąg odroczony, ale jeśli zostanie użyta await, otrzymasz ciąg jako wynik
Kluczowa różnica między async a launch. Deferred zwraca określoną wartość typu T po zakończeniu wykonywania programu Coroutine, podczas gdy Job tego nie robi.
źródło
Async vs Launch Async vs Launch Diff Image
uruchomienie / asynchronizacja bez wyniku
asynchroniczne dla wyniku
źródło