Coroutines — nyckelbegrepp, Job och Dispatchers i Kotlin

Författare: IT Sectr Publicerad: 2026-03-16 Lästid: 8 min

Coroutines (korutiner) är lätta Kotlin-trådar för asynkron programmering, tillgängliga via biblioteket kotlinx.coroutines. Enligt JetBrains Kotlin Documentation, 2026 tillåter Coroutines att pausa exekveringen av en funktion utan att blockera tråden, till skillnad från traditionella Thread. Korutiner körs på en begränsad pool av trådar, vilket gör dem tusen gånger lättare än inbyggda trådar. Kotlin Coroutines är fullt integrerade med Android Jetpack, Retrofit, Room och andra populära bibliotek i Android-ekosystemet.

Huvudpunkter

  • Coroutines — lätta Kotlin-trådar för asynkron kod utan blockering
  • Suspend-funktion — funktion som kan pausas och återupptas utan att blockera tråden
  • Dispatcher bestämmer trådpoolen för exekvering av korutinen
  • Job — deskriptor för korutinen med stöd för avbrytning och tillståndsövervakning
  • CoroutineScope hanterar livscykeln för korutiner och deras avbrytning vid slutförande

Vad är Kotlin-korutiner

Coroutines (korutiner) är en asynkron programmeringsmekanism i Kotlin, implementerad i biblioteket kotlinx.coroutines. Till skillnad från operativsystemets trådar är korutiner inte bundna till en specifik tråd: de kan pausas på en tråd och återupptas på en annan. En enda tråd kan utföra tusentals korutiner och växla mellan dem med minimal overhead.

Korutiner dök upp i Kotlin 1.3 (2018) som en experimentell funktion och blev stabila i Kotlin 1.5 (2021). Coroutines löser problemet med callback-hell på liknande sätt som async/await, men erbjuder ett rikare API: kanaler (Channel), Flow, undantagshantering i Job-hierarkin och direkt integration med Android Lifecycle.

Enligt JetBrains (2025) förbrukar varje korutin cirka 100 byte minne jämfört med 1+ MB för en inbyggd tråd. Detta gör det möjligt att köra miljontals korutiner i en enda applikation utan risk för OutOfMemoryError. Det är just korutinernas lätthet som gör dem till det föredragna verktyget för asynkronitet i Android.

Hur korutiner fungerar under huven

Varje Kotlin-korutin kompileras till en tillståndsmaskin via Continuation Passing Style (CPS). Kompilatorn lägger till en dold Continuation-parameter till varje suspend-funktion. Continuation innehåller återupptagningspunkten och alla lokala variabler. När korutinen pausas sparar runtime Continuation, och när den återupptas återställs den på valfri tillgänglig tråd från Dispatcher-poolen.

Suspend-funktioner: paus och återupptagning

suspend — Kotlin-nyckelordet som markerar en funktion som pausbar. En sådan funktion kan endast anropas från en annan suspend-funktion eller från en korutin. Inuti en suspend-funktion kan andra suspend-funktioner anropas i valfri ordning, och varje anropspunkt är en potentiell pauspunkt.

Mekaniken är enkel: när en suspend-funktion anropar en annan suspend-funktion, pausas den vid den punkten och frigör tråden. Efter att den anropade funktionen har slutförts fortsätter runtime exekveringen från den sparade platsen. Detta kallas cooperative cancellation — ingen tråd blockeras.

  • Paus — korutinen frigör tråden utan att blockera den
  • Återupptagning — korutinen fortsätter från samma plats där den pausades
  • Tråd — korutinen kan pausas på tråd A och återupptas på tråd B
  • Undantag — hanteras via try/catch precis som i synkron kod

Viktigt: en suspend-funktion är inte asynkron som standard. Exekveringsordningen förblir sekventiell om inte launch eller async används. suspend tillåter endast funktionen att pausas utan att blockera tråden och vara en del av korutinkontexten. Continuation Passing Style är en kompileringsmodell där varje suspend-funktion får en dold Continuation-callback och kompilatorn genererar en tillståndsmaskin för att hantera pauser och återupptagningar.

CoroutineScope och Structured Concurrency

CoroutineScope är en kontext som definierar livscykeln för korutiner. Alla korutiner måste startas inom en scope. När scopet avbryts (t.ex. när en Activity avslutas) avbryts alla dess underordnade korutiner automatiskt. Detta förhindrar läckage av bakgrundsuppgifter. Android Jetpack tillhandahåller färdiga scopes för varje komponent: viewModelScope för ViewModel och lifecycleScope för Activity och Fragment, som automatiskt avbryts vid förstöring av motsvarande komponent.

Structured Concurrency — principen som garanterar att en korutin inte slutförs förrän alla dess underordnade korutiner har slutförts. Job-hierarkin bildar ett träd: rotkorutinen skapar en parent job, barnen skapar child jobs. Avbrytning av parent job sprids till alla barn. Structured Concurrency är den grundläggande skillnaden mellan korutiner och trådar.

ScopeVar användsAvbrytning
GlobalScopeEndast för daemon-uppgifterAvbryts inte automatiskt
viewModelScopeAndroid ViewModelVid rensning av ViewModel
lifecycleScopeAndroid Activity/FragmentVid förstöring av lifecycle
coroutineScopeInuti en suspend-funktionVid avbrytning av parent job

SupervisorJob för felhantering

En vanlig Job avbryter vid fel i en underordnad korutin alla siblings. SupervisorJob är ett undantag: ett fel i en underordnad korutin påverkar inte de andra. Detta är viktigt när flera oberoende uppgifter körs parallellt och en kan misslyckas utan att de andra behöver avbrytas.

Dispatchers och korutinbyggare

Dispatchers bestämmer på vilka trådar korutiner exekveras. Dispatchers.Main — Androidns huvud-UI-tråd. Dispatchers.IO — pool för blockerande operationer (nätverk, disk). Dispatchers.Default — för CPU-intensiva uppgifter. Dispatchers.Unconfined — startar på den aktuella tråden men garanterar inte att den stannar där. Att välja rätt Dispatcher är avgörande för prestanda: en IO-uppgift på Default blockerar poolen för beräkningar, medan en CPU-uppgift på IO skapar onödiga trådar.

withContext — funktion för att växla Dispatcher inuti en korutin. Till exempel kan en suspend-funktion som parsar JSON växla till Dispatchers.Default under beräkningen och återgå till Dispatchers.Main för UI-uppdateringar. withContext är den mest använda byggaren inom Android-utveckling.

Tre huvudsakliga korutinbyggare

launch — startar en korutin, returnerar Job, returnerar inget resultat (fire-and-forget). async — startar en korutin, returnerar Deferred från vilket resultatet kan hämtas via await. runBlocking — blockerar den aktuella tråden för att exekvera korutinen (endast för test och main-funktioner). Val av byggare beror på scenariot: launch passar för händelser och uppdateringar, async för uppgifter med resultat, runBlocking endast för test eller startpunkter.

Kodexempel med korutiner i Kotlin

Låt oss titta på tre praktiska scenarier: grundläggande korutin med launch, parallell anrop med async och felhantering med SupervisorJob.

Starta korutin med launch

viewModelScope.launch startar en korutin i ViewModels kontext. Vid rensning av ViewModel avbryts korutinen automatiskt.

kotlin
class ProfileViewModel : ViewModel() {
    fun loadUser() {
        viewModelScope.launch(Dispatchers.IO) {
            val user = api.fetchUser()
            withContext(Dispatchers.Main) {
                showUser(user)
            }
        }
    }
}

Parallella förfrågningar med async

coroutineScope med async startar tre förfrågningar parallellt. Resultaten samlas in via .await(). Om någon förfrågan misslyckas avbryts alla.

kotlin
suspend fun loadDashboard(): Dashboard = coroutineScope {
    val user = async { api.fetchUser() }
    val posts = async { api.fetchPosts() }
    val stats = async { api.fetchStats() }
    Dashboard(user.await(), posts.await(), stats.await())
}

Felhantering med SupervisorJob

SupervisorJob låter varje korutin slutföras oberoende. Ett fel i en förfrågan avbryter inte de andra.

kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
    try { api.fetchUsers() } catch (e: Exception) { log(e) }
}
scope.launch {
    try { api.fetchPosts() } catch (e: Exception) { log(e) }
}

Korutiner vs trådar: jämförelse och scenarier

Trådar (Thread) — operativsystemets primitiv. Varje tråd har en egen stack (~1 MB) och kräver systemanrop för skapande och växling. Korutiner — språkets primitiv, inte bundet till OS. De använder Continuation för att spara tillstånd och växlar på runtime-nivå utan systemanrop.

  • Minne — tråd ~1 MB, korutin ~100 byte. Skillnad på 10 000 gånger
  • Skapande — tråd ~1 µs syscall, korutin ~0.01 µs på JVM-nivå
  • Växling — tråd ~0.1 µs (syscall), korutin ~0.001 µs (continuation)
  • Maximum — tusentals trådar vs miljontals korutiner på en enhet
  • Avbrytning — tråd kan inte avbrytas utifrån (föråldrad Thread.stop), korutin kan via Job.cancel()

Enligt Google (2025) minskar användning av korutiner istället för trådar minnesförbrukningen för bakgrundsuppgifter i Android-applikationer med 90–95%. Alla moderna Android-bibliotek (Retrofit, Room, WorkManager) har inbyggt stöd för korutiner via suspend-funktioner. Ktor (JetBrains HTTP-klientramverk) är också helt byggt på korutiner och tillhandahåller suspend-funktioner för varje förfrågan utan callback-API. Room stöder korutiner via suspend-funktioner i DAO, vilket gör det möjligt att utföra databasfrågor utan att blockera huvudtråden.

När ska man använda trådar istället för korutiner

Trådar förblir nödvändiga för inbyggd kod via JNI, blockerande CPU-intensiva anrop utan tidsbegränsning (videorendering, simuleringar) och vid integration med C-bibliotek. För allt annat — korutiner.

Vanliga frågor

Vad är skillnaden mellan en korutin och en tråd?

Korutin — en pausbar arbetsenhet som körs på en befintlig tråd. En tråd är en systemresurs med egen stack. Korutiner är tusentals gånger lättare än trådar och blockerar inte resurser vid paus.

Vad är Dispatchers.IO och hur skiljer det sig från Default?

Dispatchers.IO är avsett för blockerande I/O-operationer (nätverk, filer) och kan skapa nya trådar vid behov. Dispatchers.Default har en pool med fast storlek (antal CPU-kärnor) för CPU-intensiva beräkningar.

Hur avbryter jag en korutin som körs?

Job.cancel() avbryter korutinen och alla dess barn. För att kontrollera avbrytning inuti korutinen, använd ensureActive() — den kastar CancellationException om korutinen är avbruten.

Kan jag använda korutiner med RxJava?

Ja — via biblioteket kotlinx-coroutines-rx3. Det tillhandahåller funktionerna awaitSingle, awaitFirst och andra för att konvertera Observable/Single till suspend-funktioner och tillbaka via flowable.

Vad är Flow i korutiner?

Flow — en kall asynkron dataström, motsvarigheten till RxJava Observable för korutiner. Flow sänder ut värden sekventiellt och avslutas med ett undantag eller framgång. Stöder operatorerna map, filter, catch och andra.

Sammanfattning

  • Coroutines — lätta Kotlin-trådar med paus utan blockering via Continuation Passing Style
  • suspend — nyckelord för att markera pausbara funktioner
  • Dispatchers hanterar trådpoolen: Main, IO, Default respektive
  • CoroutineScope binder korutinernas livscykel till komponenten (Activity, ViewModel)
  • launch startar korutin utan resultat, async/await — med resultat
  • Structured Concurrency garanterar hierarkisk avbrytning av underordnade korutiner
  • Korutiner vs trådar — korutiner är 10 000 gånger lättare och är standard för Android

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också