Da ich Coroutinen nur für JVM verwendet habe, werde ich über das JVM-Backend sprechen. Es gibt auch Kotlin Native und Kotlin JavaScript, aber diese Backends für Kotlin liegen außerhalb meines Anwendungsbereichs.
Beginnen wir also mit dem Vergleich von Kotlin-Coroutinen mit Coroutinen anderer Sprachen. Grundsätzlich sollten Sie wissen, dass es zwei Arten von Coroutinen gibt: stapellos und stapelbar. Kotlin implementiert stapellose Coroutinen - dies bedeutet, dass Coroutine keinen eigenen Stapel hat und die Möglichkeiten von Coroutine ein wenig einschränken. Eine gute Erklärung können Sie hier lesen .
Beispiele:
- Stapellos: C #, Scala, Kotlin
- Stapelbar: Quasar, Javaflow
Was bedeutet es, dass Coroutine wie ein leichter Faden ist?
Dies bedeutet, dass Coroutine in Kotlin keinen eigenen Stack hat, nicht auf einem nativen Thread abgebildet wird und keine Kontextumschaltung auf einem Prozessor erforderlich ist.
Was ist der Unterschied?
Thread - präventiv Multitasking. ( normalerweise ). Coroutine - kooperatives Multitasking.
Thread - wird normalerweise vom Betriebssystem verwaltet. Coroutine - von einem Benutzer verwaltet.
Laufen Kotlins Coroutinen tatsächlich parallel / gleichzeitig?
Es hängt davon ab, ob Sie jede Coroutine in einem eigenen Thread ausführen oder alle Coroutinen in einem Thread oder einem festen Thread-Pool ausführen können.
Mehr darüber, wie Coroutinen ausgeführt werden, finden Sie hier .
Selbst in einem Mehrkernsystem läuft immer nur eine Coroutine (stimmt das?)
Nein, siehe vorherige Antwort.
Hier starte ich 100000 Coroutinen. Was passiert hinter diesem Code?
Eigentlich kommt es darauf an. Angenommen, Sie schreiben den folgenden Code:
fun main(args: Array<String>) {
for (i in 0..100000) {
async(CommonPool) {
delay(1000)
}
}
}
Dieser Code wird sofort ausgeführt.
Weil wir auf die Ergebnisse des async
Anrufs warten müssen .
Lassen Sie uns das beheben:
fun main(args: Array<String>) = runBlocking {
for (i in 0..100000) {
val job = async(CommonPool) {
delay(1)
println(i)
}
job.join()
}
}
Wenn Sie dieses Programm ausführen, erstellt kotlin 2 * 100000 Instanzen von Continuation
, was einige Dutzend MB RAM beansprucht , und in der Konsole werden Zahlen von 1 bis 100000 angezeigt.
Schreiben wir diesen Code also folgendermaßen um:
fun main(args: Array<String>) = runBlocking {
val job = async(CommonPool) {
for (i in 0..100000) {
delay(1)
println(i)
}
}
job.join()
}
Was erreichen wir jetzt? Jetzt erstellen wir nur 100001 Instanzen von Continuation
, und das ist viel besser.
Jede erstellte Fortsetzung wird auf CommonPool (einer statischen Instanz von ForkJoinPool) gesendet und ausgeführt.