Nebenläufigkeit und Multithreading in Kotlin: Vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten
```html

Einführung in Nebenläufigkeit und Multithreading in Kotlin



Moderne Anwendungen erfordern zunehmend die gleichzeitige Ausführung mehrerer Aufgaben – von der Verarbeitung von Netzwerkanfragen bis zur Arbeit mit Datenbanken. In der Sprache Kotlin, die aktiv für die Entwicklung unter Android, Serveranwendungen (Ktor, Spring) und sogar Desktop-Lösungen eingesetzt wird, sind leistungsstarke Werkzeuge für die Arbeit mit Nebenläufigkeit und Multithreading implementiert.



In diesem Artikel werden wir die wichtigsten Konzepte behandeln: traditionelle Threads, Coroutines – den modernen Ansatz für Asynchronität in Kotlin – sowie Synchronisationsmechanismen. Sie erfahren, wann Sie Threads und wann Sie Coroutines verwenden sollten, und erhalten fertige Codebeispiele.



1. Traditionelle Threads in Kotlin



Kotlin ist vollständig kompatibel mit Java, daher können Sie die Standardklassen Thread und Runnable verwenden. Kotlin fügt jedoch syntaktischen Zucker hinzu, der den Code prägnanter macht.



Erstellen und Starten eines Threads



Die grundlegende Methode zum Erstellen eines Threads besteht darin, ein Lambda an den Konstruktor Thread zu übergeben:



fun main() {    val thread = Thread {        println("Thread gestartet: ${Thread.currentThread().name}")        for (i in 1..5) {            println("Zähler: $i")            Thread.sleep(500)        }    }    thread.start()    println("Hauptthread läuft weiter")    thread.join() // warten auf das Ende des Threads    println("Hauptthread beendet")}


In diesem Beispiel haben wir einen Thread erstellt, der Zahlen von 1 bis 5 mit einer Verzögerung von 500 ms ausgibt. Die Methode join() zwingt den Hauptthread, auf das Ende des untergeordneten Threads zu warten.



Probleme mit Threads



  • Hoher Ressourcenverbrauch – jeder Thread benötigt einen eigenen Speicher-Stack (normalerweise 1 MB).
  • Komplexität der Synchronisation – bei der Arbeit mit gemeinsamen Daten kann leicht ein Race Condition entstehen.
  • Begrenzte Anzahl – auf einem Gerät können nicht Zehntausende von Threads ohne Leistungseinbußen gestartet werden.


Aus diesem Grund wurden in Kotlin Coroutines eingeführt – eine leichtere Alternative.



2. Coroutines – moderne Nebenläufigkeit in Kotlin



Coroutines sind leichtgewichtige Threads, die ihre Ausführung unterbrechen können, ohne den Systemthread zu blockieren. Sie sind das wichtigste Werkzeug für asynchrone Programmierung in Kotlin.



Einbinden von Coroutines



Um mit Coroutines zu arbeiten, muss die Abhängigkeit in build.gradle.kts hinzugefügt werden:



dependencies {    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")}


Basisbeispiel einer Coroutine



import kotlinx.coroutines.*

fun main() = runBlocking { println("Start der Arbeit im Thread: ${Thread.currentThread().name}")

launch { // Start einer neuen Coroutine delay(1000) // nicht-blockierende Verzögerung println("Coroutine: ${Thread.currentThread().name}") }

println("Haupt-Coroutine läuft weiter") delay(2000) // warten auf das Ende der untergeordneten Coroutine println("Ende")}


Wichtige Punkte:

  • runBlocking – Brücke zwischen normalem Code und Coroutines (blockiert den aktuellen Thread).
  • launch – startet eine Coroutine, die kein Ergebnis zurückgibt.
  • delay – nicht-blockierende Verzögerung, im Gegensatz zu Thread.sleep().


Async und await zum Abrufen eines Ergebnisses



Wenn eine Coroutine einen Wert zurückgeben soll, verwenden Sie async:



fun main() = runBlocking {    val deferred1 = async {        delay(1000)        "Ergebnis 1"    }    val deferred2 = async {        delay(500)        "Ergebnis 2"    }

println("Warte auf Ergebnisse...") val result1 = deferred1.await() val result2 ```

Blogs

Buchempfehlungen