Sobes.tech
Middle

Welche Elemente der Multithreading bietet Kotlin?

sobes.tech KI

Antwort von AI

Kotlin bietet die folgenden Elemente der Nebenläufigkeit:

  • Coroutines: Leichtgewichtige Threads, basierend auf suspendierenden Funktionen. Ermöglichen die asynchrone und nicht blockierende Ausführung von Code.
  • Coroutine-Bauer: Funktionen, die Coroutines starten. Hauptsächlich: launch (startet eine Coroutine ohne Rückgabewert), async (startet eine Coroutine und gibt ein Deferred zurück, das erwartet werden kann, um das Ergebnis zu erhalten).
    // Beispiel für die Verwendung von launch
    GlobalScope.launch {
        println("Hallo aus der Coroutine ${Thread.currentThread().name}")
    }
    
    // Beispiel für die Verwendung von async
    val deferred = GlobalScope.async {
        delay(1000) // Simuliert eine lange Operation
        "Ergebnis"
    }
    val result = runBlocking { deferred.await() } // Erwartet das Ergebnis
    
  • Dispatchers: Bestimmen, auf welchem Thread-Pool die Coroutine ausgeführt wird. Hauptsächlich:
    • Dispatchers.Default: Allgemeiner Thread-Pool für CPU-intensive Aufgaben.
    • Dispatchers.IO: Thread-Pool für blockierende Ein-/Ausgabe-Operationen (Dateien, Netzwerk).
    • Dispatchers.Main: Dispatcher für den UI-Thread auf entsprechenden Plattformen (Android, Swing).
    • Dispatchers.Unconfined: Die Coroutine startet im aktuellen Thread, kann aber in jedem Thread wieder aufgenommen werden.
    GlobalScope.launch(Dispatchers.IO) {
        // Ausführung von Ein-/Ausgabe
    }
    
  • runBlocking: Konstruktorfunktion für Coroutine, die den aktuellen Thread blockiert, bis die Coroutine beendet ist. Wird verwendet, um blockierenden und nicht blockierenden Code zu kombinieren, oft in Tests oder main-Funktionen.
    runBlocking {
        launch {
            delay(500)
            println("Abgeschlossen in ${Thread.currentThread().name}")
        }
        println("Gestartet in ${Thread.currentThread().name}")
    }
    
  • suspend-Funktionen: Funktionen, deren Ausführung unterbrochen und wieder aufgenommen werden kann. Können nur aus anderen suspend-Funktionen oder Coroutine-Bauern aufgerufen werden.
    suspend fun doSomething() {
        delay(100) // Beispiel für eine Unterbrechung
    }
    
  • Job: Handle für eine laufende Coroutine. Bietet Methoden zur Steuerung des Lebenszyklus der Coroutine (Abbrechen, Warten auf Abschluss).
    val job = GlobalScope.launch {
       // Lange Operation
    }
    job.cancel() // Coroutine abbrechen
    runBlocking { job.join() } // Auf Abschluss warten
    
  • CoroutineScope: Definiert einen Geltungsbereich für Coroutines. Coroutines, die in einem bestimmten Bereich gestartet werden, werden beim Abbrechen des Bereichs automatisch abgebrochen. Hilft bei der Verwaltung des Lebenszyklus von Coroutines.
    val scope = CoroutineScope(Dispatchers.Default)
    scope.launch {
        // Coroutine in diesem Bereich
    }
    scope.cancel() // Alle Coroutines in diesem Bereich abbrechen
    
  • Kanäle (Channel): Primitive für die sichere Datenübertragung zwischen Coroutines. Kanäle können unidirektional (nur Senden oder Empfangen) oder bidirektional sein.
    import kotlinx.coroutines.channels.Channel
    
    val channel = Channel<Int>()
    
    runBlocking {
        launch {
            for (x in 1..5) channel.send(x * x)
            channel.close() // Kanal schließen
        }
        launch {
            for (y in channel) println(y)
        }
    }
    
  • Mutex (Mutex): Synchronisationsprimitive, um exklusiven Zugriff auf eine gemeinsame Ressource zu gewährleisten. Sichert die Thread-Sicherheit, indem nur eine Coroutine den Mutex zu einem Zeitpunkt besitzt.
    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock {
            counter++
        }
    }
    
  • Zustände (StateFlow, SharedFlow): Primitive für die Arbeit mit Datenströmen im Kontext der reaktiven Programmierung und Nebenläufigkeit. StateFlow stellt einen "kalten" Strom mit aktuellem Zustand dar, SharedFlow einen "heißen" Strom für die breitgestreute Datenübertragung.