async: mi ez, Deferred és párhuzamos korutinok hogyan működnek

Szerző: IT Sectr Megjelenés: 2026-06-22 Olvasási idő: 8 perc

async — Coroutine Builder Kotlinban, amely elindít egy korutint és egy Deferred<T> objektumot ad vissza az aszinkron művelet eredményének lekéréséhez. Az async lehetővé teszi több feladat párhuzamos végrehajtását és azok eredményeinek összesítését az await()-en keresztül. A JetBrains, 2024 útmutatója szerint az async a preferált módszer a párhuzamos számítások szervezésére korutinokban.

Főbb pontok

  • async — korutin-építő, amely Deferred<T>-t ad vissza az aszinkron művelet eredményével
  • Deferred — aszinkron ígéret, amely örökli a Job-ot, az await() metódussal az eredmény lekéréséhez
  • async lehetővé teszi a független feladatok párhuzamos végrehajtását, csökkentve a teljes időt
  • await() — szuszpendáló függvény, amely blokkolás nélkül felfüggeszti a korutint az eredmény beérkezéséig
  • Strukturált konkurencia az async segítségével garantálja az összes párhuzamos feladat megszakítását hiba esetén

Mi az async a Kotlin Coroutines-ben?

async — egy CoroutineScope kiterjesztő függvény, amely korutint hoz létre eredmény-visszaadással. A launch-tól eltérően az async Deferred<T>-t ad vissza — egy objektumot, amely egy jövőbeli értéket képvisel. Az async segítségével elindított korutin más korutinokkal konkurensen hajtódik végre, lehetővé téve a számítások párhuzamosítását.

Az async akkor használatos, amikor az aszinkron művelet eredménye szükséges a további feldolgozáshoz: adatok betöltése több forrásból, gyűjtemények kötegelt feldolgozása, párhuzamos kérések különböző API-khoz. Deferred azonnal létrejön, és az eredmény a korutin befejezése után válik elérhetővé.

kotlin
import kotlinx.coroutines.*

suspend fun String.delayedValue(): String {
    delay(1000L)
    return this
}

fun main() = runBlocking {
    val deferred: Deferred<String> = async { "Hello".delayedValue() }
    println(deferred.await())
}

Az async és Deferred szintaxis

Az async aláírása hasonló a launch-hoz: ugyanazok a CoroutineContext, CoroutineStart paraméterek és szuszpendáló blokk. A különbség a visszaadott típusban van — Deferred<T> a Job helyett, ahol T a blokk utolsó kifejezése által visszaadott eredmény típusa.

kotlin
public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T>

Deferred<T> — interfész, amely örökli a Job-ot és hozzáadja az await(), getCompleted(), getCompletionExceptionOrNull() metódusokat. Az await() szuszpendáló függvény, és csak korutinon belül vagy más szuszpendáló függvényben hívható meg. A getCompleted() — nem blokkoló metódus, amely kivételt dob, ha a korutin még nem fejeződött be.

Párhuzamos feladatok async segítségével

Az async fő előnye a feladatok párhuzamos indításának lehetősége. A szekvenciális várakozás helyett (teljes idő = idők összege) az async egyidejűleg indítja a korutinokat, csökkentve a teljes időt a leghosszabb művelet idejére.

Párhuzamos adatbetöltés

Tipikus forgatókönyv — a felhasználói profil, beállítások és rendelési előzmények betöltése három párhuzamos async kéréssel. Mindhárom befejezése után az eredmények egyetlen adatmodellbe egyesülnek.

kotlin
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
    val profile = async { api.getProfile(userId) }
    val settings = async { api.getSettings(userId) }
    val orders = async { api.getRecentOrders(userId) }

    Dashboard(
        profile = profile.await(),
        settings = settings.await(),
        orders = orders.await()
    )
}

A coroutineScope függvény elindítja a gyermek korutinokat, és megvárja a befejezésüket, mielőtt visszaadja az eredményt. Az egész blokk párhuzamosan hajtódik végre, nem szekvenciálisan.

Deferred eredmények feldolgozása

A Deferred több metódust támogat az eredménnyel való munkához. Az await() mellett elérhetők metódusok az állapot ellenőrzésére, a kész érték lekérésére és több Deferred aggregálására a Kotlin Coroutines segédfüggvényein keresztül.

MetódusLeírásSuspend?
await()Felfüggeszti a korutint az eredmény beérkezéséigIgen
getCompleted()Visszaadja az eredményt, ha a korutin befejeződött (egyébként Exception)Nem
getCompletionExceptionOrNull()Hiba esetén visszaadja a kivételt vagy null-tNem
isCompletedEllenőrzi, hogy a korutin befejeződött-eNem

Deferred lista aggregálásához az awaitAll() használatos — egy függvény, amely felfüggeszti a végrehajtást, amíg a gyűjtemény összes Deferred-je be nem fejeződik. Ha legalább egy hiba miatt fejeződött be, az awaitAll() kivételt dob.

kotlin
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
    return coroutineScope {
        val deferreds = requests.map { async { it() } }
        deferreds.awaitAll()
    }
}

Különbségek az async és launch között

Az async és launch közötti választás attól függ, hogy szükség van-e a korutin végrehajtásának eredményére. A launch Job-ot ad vissza, és fire-and-forget műveletekhez alkalmas, az async Deferred-et ad vissza, és adatokat visszaadó feladatokhoz használatos. Szintaxis és paraméterek tekintetében az építők azonosak.

  • launch → Job (nincs eredmény), async → Deferred<T> (van T eredmény)
  • launch — fire-and-forget feladatok (naplózás, gyorsítótárazás, analitika küldése)
  • async — párhuzamos számítások (betöltés több API-ból, kötegelt feldolgozás)
  • Mindkettő támogatja a strukturált konkurenciát és a CoroutineStart paramétereket
  • az await() csak Deferred esetén érhető el, a launch nem biztosít eredményt

Fontos szabály: soha ne használjuk az async-ot fire-and-forget-re. Ha a korutin eredménye nem szükséges, használjuk a launch-ot. Az async többletterhelést jelent a Deferred létrehozásában, ami ilyen forgatókönyvben nem indokolt.

Async példák mobilfejlesztésben

Androidban az async párhuzamos műveletekhez használatos a ViewModel-en és UseCases-eken belül. Tipikus forgatókönyvek: profil és hírfolyam egyidejű betöltése, időjárás lekérése több meteorológiai szolgáltatástól, adatok kötegelt szinkronizálása a szerverrel.

kotlin
class HomeViewModel : ViewModel() {
    fun loadHomeScreen() {
        viewModelScope.launch {
            val userData = async(Dispatchers.IO) { repository.getUserData() }
            val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
            val notifications = async(Dispatchers.IO) { repository.getNotifications() }

            val state = HomeState(
                user = userData.await(),
                news = newsFeed.await(),
                unread = notifications.await()
            )
            _uiState.update { state }
        }
    }
}

Javasolt az async csoportot coroutineScope vagy supervisorScope csomagolni a hibák elkülönítéséhez. A supervisorScope lehetővé teszi a többi async korutin végrehajtásának folytatását még akkor is, ha az egyikben hiba történik — hasznos nem kritikus műveleteknél.

Gyakran Ismételt Kérdések

Használható az async await nélkül?

Használható, de értelmetlen. Az async await() nélkül elindítja a korutint, de az eredménye elveszik. Ha az eredmény nem szükséges, használjuk a launch-ot — az nem hoz létre Deferred-et, és hatékonyabb memória és teljesítmény szempontjából.

Hogyan kezeli az async a kivételeket?

Az async belsejében lévő kivétel a Deferred-ben tárolódik. Az await() hívás továbbítja ezt a kivételt. A továbbítás nélküli ellenőrzéshez használjuk a getCompletionExceptionOrNull()-t. A coroutineScope használatakor a hiba megszakítja az összes gyermek korutint.

Mi az awaitAll a Kotlin Coroutines-ben?

awaitAll() — kiterjesztő függvény az Iterable<Deferred<T>> számára, amely felfüggeszti a korutint, amíg az összes Deferred be nem fejeződik. Visszaadja az eredmények listáját. Ha legalább egy Deferred hiba miatt fejeződik be, továbbítja a kivételt és megszakítja a többit.

Különbözik az async a GlobalScope.async-tól?

Igen. Az async a CoroutineScope kiterjesztő függvénye, a scope-hoz kötve. A GlobalScope.async korutint hoz létre az életciklushoz való kötődés nélkül — végtelenül futhat. Androidban a GlobalScope nem ajánlott a memóriaszivárgás kockázata miatt.

Hány async korutin indítható párhuzamos kérésekhez?

A számot az ütemező határozza meg: a Dispatchers.IO akár 64 egyidejű szálat támogat, a Dispatchers.Default — a CPU magok számának megfelelően. Tömeges műveletekhez használjunk korlátozott párhuzamosságot Semaphore vagy mapNotNull segítségével awaitAll-lel.

Összefoglaló

  • async — korutin-építő, amely Deferred<T>-t ad vissza aszinkron eredménylekéréshez
  • Deferred örökli a Job-ot és hozzáadja az await(), getCompleted(), getCompletionExceptionOrNull() metódusokat
  • Párhuzamos végrehajtás async segítségével csökkenti a teljes időt a leghosszabb művelet időtartamára
  • awaitAll() — segédeszköz az összes Deferred várakozásához egy gyűjteményben
  • coroutineScope — ajánlott burkoló egy async csoporthoz megszakítási garanciával
  • Ne használjuk az async-ot fire-and-forget-re — alkalmazzuk a launch-ot
  • Androidban az async párhuzamos betöltéshez használatos ViewModel-ben viewModelScope segítségével

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is