Sobes.tech
Middle

Jakie elementy wielowątkowości zapewnia Kotlin?

sobes.tech AI

Odpowiedź od AI

Kotlin zapewnia następujące elementy współbieżności:

  • Korutyny: Lekkie wątki oparte na funkcjach zawieszalnych. Umożliwiają asynchroniczne i nieblokujące wykonywanie kodu.
  • Budowniczy korutyn: Funkcje uruchamiające korutyny. Główne: launch (uruchamia korutynę bez zwracania wartości), async (uruchamia korutynę i zwraca Deferred, które można oczekiwać, aby uzyskać wynik).
    // Przykład użycia launch
    GlobalScope.launch {
        println("Cześć z korutyny ${Thread.currentThread().name}")
    }
    
    // Przykład użycia async
    val deferred = GlobalScope.async {
        delay(1000) // Symuluje długą operację
        "Wynik"
    }
    val result = runBlocking { deferred.await() } // Oczekuje na wynik
    
  • Dispatchers: Określają, z którego puli wątków będzie wykonywana korutyna. Główne:
    • Dispatchers.Default: Ogólna pula wątków dla zadań intensywnych CPU.
    • Dispatchers.IO: Pula wątków dla operacji wejścia/wyjścia blokujących (pliki, sieć).
    • Dispatchers.Main: Dispatcher dla wątku interfejsu użytkownika na odpowiednich platformach (Android, Swing).
    • Dispatchers.Unconfined: Korutyna uruchamia się w bieżącym wątku, ale może zostać wznowiona w dowolnym wątku.
    GlobalScope.launch(Dispatchers.IO) {
        // Wykonanie wejścia/wyjścia
    }
    
  • runBlocking: Funkcja budująca korutynę, która blokuje bieżący wątek do czasu zakończenia korutyny. Używana do łączenia kodu blokującego i nieblokującego, często w testach lub funkcjach main.
    runBlocking {
        launch {
            delay(500)
            println("Zakończono w ${Thread.currentThread().name}")
        }
        println("Uruchomiono w ${Thread.currentThread().name}")
    }
    
  • Funkcje suspend: Funkcje, których wykonanie może zostać zawieszone i wznowione. Mogą być wywoływane tylko z innych funkcji suspend lub budowniczych korutyn.
    suspend fun doSomething() {
        delay(100) // Przykład zawieszenia
    }
    
  • Job: uchwyt do uruchomionej korutyny. Zapewnia metody do zarządzania cyklem życia korutyny (anulowanie, oczekiwanie na zakończenie).
    val job = GlobalScope.launch {
       // Długa operacja
    }
    job.cancel() // Anuluj korutynę
    runBlocking { job.join() } // Oczekuj na zakończenie
    
  • CoroutineScope: Określa zakres widoczności dla korutyn. Korutyny uruchomione w określonym zakresie są automatycznie anulowane przy anulowaniu zakresu. Pomaga zarządzać cyklem życia korutyn.
    val scope = CoroutineScope(Dispatchers.Default)
    scope.launch {
        // Korutyna w tym zakresie
    }
    scope.cancel() // Anuluj wszystkie korutyny w tym zakresie
    
  • Kanały (Channel): Primitive do bezpiecznego przesyłania danych między korutynami. Kanały mogą być jednokierunkowe (tylko wysyłanie lub odbieranie) lub dwukierunkowe.
    import kotlinx.coroutines.channels.Channel
    
    val channel = Channel<Int>()
    
    runBlocking {
        launch {
            for (x in 1..5) channel.send(x * x)
            channel.close() // Ważne, aby zamknąć kanał
        }
        launch {
            for (y in channel) println(y)
        }
    }
    
  • Mutex (Mutex): Primitive synchronizacji zapewniający wyłączny dostęp do wspólnego zasobu. Zapewnia bezpieczeństwo wątków, pozwalając tylko jednej korutynie posiadać mutex w danym momencie.
    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock {
            counter++
        }
    }
    
  • Stany (StateFlow, SharedFlow): Primitive do pracy z przepływami danych w kontekście programowania reaktywnego i współbieżności. StateFlow reprezentuje "zimny" strumień z aktualnym stanem, a SharedFlow - "gorący" strumień do szerokiego rozgłaszania danych.