Czym jest coroutine w Kotlin i jak działa?
sobes.tech AI
Odpowiedź od AI
Krotina w Kotlinie to lekka jednostka wykonawcza, która pozwala na pisanie kodu asynchronicznego i nieblokującego w bardziej czytelny i sekwencyjny sposób. Jest podobna do wątku (thread), ale znacznie lżejsza i może być tworzona w dużej ilości.
Główne komponenty i zasady działania:
- Funkcje zawieszone (Suspend Functions): Funkcje oznaczone słowem kluczowym
suspend, które mogą zawiesić swoje wykonanie bez blokowania wątku, na którym są wykonywane. Gdy zawieszona funkcja kończy operację "oczekiwania" (np. zapytanie sieciowe), może wznowić wykonanie od miejsca zawieszenia. - Kontekst (Kontekst korutyny): Zbiór elementów kontrolujących zachowanie korutyny. Wchodzi w skład:
Job: Deskryptor korutyny, umożliwiający zarządzanie jej cyklem życia (anulowanie, oczekiwanie na zakończenie).CoroutineDispatcher: Określa wątek(-i), na którym(-ych) będzie wykonywana korutyna. Umożliwia przełączanie między wątkami.CoroutineName: Opcjonalna nazwa do debugowania.CoroutineExceptionHandler: Obsługa nieobsłużonych wyjątków.
- Budowniczy (Builder): Funkcje uruchamiające wykonanie korutyn:
launch: Uruchamia nową korutynę, nie zwracając wyniku. ZwracaJob.async: Uruchamia nową korutynę, zwracającą wynik (Deferred). Aby uzyskać wynik, używa się.await().runBlocking: Budowniczy blokujący, używany głównie do testów lub integracji z blokującym kodem.
Jak to działa od kuchni:
Korutyny nie tworzą osobnych wątków dla każdego zadania. Zamiast tego, gdy funkcja suspend jest zawieszona, kompilator generuje kod, który zapisuje aktualny stan obliczeń. Gdy wynik jest dostępny, korutyna jest wznawiana na jednym z wątków zarządzanych przez CoroutineDispatcher. Jest to osiągane przez przekształcenie funkcji suspend w wywołania asynchroniczne z kontynuacjami, co pozwala jednemu wątkowi wykonywać wiele korutyn, przełączając się między nimi podczas zawieszenia.
Przykład:
import kotlinx.coroutines.*
fun main() = runBlocking { // Blokuje bieżący wątek do czasu zakończenia korutyny w runBlocking
println("Najpierw")
launch { // Uruchamia nową korutynę w tle
delay(1000L) // Nieblokujące opóźnienie na 1 sekundę
println("Po opóźnieniu")
}
println("Potem") // Ta linijka wykona się przed zakończeniem korutyny launch
}
Wynik tego kodu będzie:
Najpierw
Potem
Po opóźnieniu
To demonstruje nieblokujący charakter launch i delay.