async: Was es ist, Deferred und wie parallele Coroutinen funktionieren

Autor: IT Sectr Veröffentlicht: 2026-06-22 Lesezeit: 8 Min.

async — ist ein Coroutine Builder in Kotlin, der eine Coroutine startet und ein Deferred<T>-Objekt zurückgibt, um das Ergebnis einer asynchronen Operation zu erhalten. async ermöglicht die parallele Ausführung mehrerer Aufgaben und die Aggregation ihrer Ergebnisse über await(). Laut JetBrains-Leitfaden, 2024 ist async die bevorzugte Methode zur Organisation paralleler Berechnungen in Coroutinen.

Wichtigste Erkenntnisse

  • async — ein Coroutine Builder, der Deferred<T> mit dem Ergebnis einer asynchronen Operation zurückgibt
  • Deferred — ein asynchrones Versprechen, das Job erbt, mit der Methode await() zum Abrufen des Ergebnisses
  • async ermöglicht die parallele Ausführung unabhängiger Aufgaben und reduziert die Gesamtzeit
  • await() — eine Suspend-Funktion, die die Coroutine anhält, bis das Ergebnis ohne Blockierung vorliegt
  • Strukturierte Nebenläufigkeit mit async garantiert den Abbruch aller parallelen Aufgaben bei Fehlern

Was ist async in Kotlin Coroutines?

async — ist eine CoroutineScope-Erweiterungsfunktion, die eine Coroutine erstellt, die ein Ergebnis zurückgibt. Im Gegensatz zu launch gibt async Deferred<T> zurück — ein Objekt, das einen zukünftigen Wert repräsentiert. Eine über async gestartete Coroutine wird gleichzeitig mit anderen Coroutinen ausgeführt, was die Parallelisierung von Berechnungen ermöglicht.

async wird verwendet, wenn das Ergebnis einer asynchronen Operation für die weitere Verarbeitung benötigt wird: Laden von Daten aus mehreren Quellen, Stapelverarbeitung von Sammlungen, parallele Anfragen an verschiedene APIs. Deferred wird sofort erstellt, und das Ergebnis wird nach Abschluss der Coroutine verfügbar.

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())
}

Syntax von async und Deferred

Die Signatur von async ähnelt launch: dieselben Parameter CoroutineContext, CoroutineStart und ein Suspend-Block. Der Unterschied liegt im Rückgabetyp — Deferred<T> statt Job, wobei T der Ergebnistyp ist, der vom letzten Ausdruck des Blocks zurückgegeben wird.

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

Deferred<T> — ein Interface, das Job erbt und die Methoden await(), getCompleted(), getCompletionExceptionOrNull() hinzufügt. await() ist eine Suspend-Funktion und kann nur innerhalb einer Coroutine oder einer anderen Suspend-Funktion aufgerufen werden. getCompleted() ist eine nicht blockierende Methode, die eine Ausnahme auslöst, wenn die Coroutine noch nicht abgeschlossen ist.

Parallele Aufgaben mit async

Der Hauptvorteil von async ist die Möglichkeit, Aufgaben parallel auszuführen. Anstatt auf jede Operation nacheinander zu warten (Gesamtzeit = Summe der Zeiten), startet async Coroutinen gleichzeitig und reduziert die Gesamtzeit auf die Dauer der längsten Operation.

Paralleles Datenladen

Ein typisches Szenario — Laden des Benutzerprofils, seiner Einstellungen und des Bestellverlaufs mit drei parallelen async-Anfragen. Nach Abschluss aller drei werden die Ergebnisse zu einem einzigen Datenmodell zusammengeführt.

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()
    )
}

Die Funktion coroutineScope startet untergeordnete Coroutinen und wartet auf deren Abschluss, bevor sie das Ergebnis zurückgibt. Der gesamte Block wird parallel ausgeführt, nicht sequenziell.

Verarbeitung von Deferred-Ergebnissen

Deferred unterstützt mehrere Methoden zur Arbeit mit dem Ergebnis. Neben await() gibt es Methoden zum Überprüfen des Status, zum Abrufen eines abgeschlossenen Werts und zum Aggregieren mehrerer Deferreds über die Hilfsfunktionen von Kotlin Coroutines.

MethodeBeschreibungSuspend?
await()Hält die Coroutine an, bis das Ergebnis vorliegtJa
getCompleted()Gibt das Ergebnis zurück, wenn die Coroutine abgeschlossen ist (sonst Exception)Nein
getCompletionExceptionOrNull()Gibt die Ausnahme bei Fehler oder null zurückNein
isCompletedÜberprüft, ob die Coroutine abgeschlossen istNein

Zur Aggregation einer Liste von Deferreds wird awaitAll() verwendet — eine Funktion, die die Ausführung anhält, bis alle Deferreds in der Sammlung abgeschlossen sind. Wenn mindestens einer fehlerhaft abgeschlossen wurde, löst awaitAll() die Ausnahme aus.

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

Unterschiede zwischen async und launch

Die Wahl zwischen async und launch hängt davon ab, ob das Ergebnis der Coroutine benötigt wird. launch gibt Job zurück und eignet sich für Fire-and-Forget-Operationen, async gibt Deferred zurück und wird für Aufgaben verwendet, die Daten zurückgeben. In Bezug auf Syntax und Parameter sind die Builder identisch.

  • launch → Job (kein Ergebnis), async → Deferred<T> (Ergebnis T)
  • launch — Fire-and-Forget-Aufgaben (Logging, Caching, Senden von Analysen)
  • async — parallele Berechnungen (Laden von mehreren APIs, Stapelverarbeitung)
  • Beide unterstützen strukturierte Nebenläufigkeit und CoroutineStart-Parameter
  • await() ist nur für Deferred verfügbar, launch liefert kein Ergebnis

Wichtige Regel: Verwenden Sie async niemals für Fire-and-Forget. Wenn das Ergebnis der Coroutine nicht benötigt wird, verwenden Sie launch. async erzeugt Overhead durch die Erstellung von Deferred, der in solchen Szenarien nicht gerechtfertigt ist.

async-Beispiele in der mobilen Entwicklung

In Android wird async für parallele Operationen innerhalb von ViewModel und UseCases verwendet. Typische Szenarien: gleichzeitiges Laden von Profil und Nachrichtenfeed, Abrufen von Wetterdaten von mehreren Wetterdiensten, Batch-Datensynchronisation mit dem Server.

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 }
        }
    }
}

Es wird empfohlen, eine Gruppe von async-Aufrufen in coroutineScope oder supervisorScope zu kapseln, um Fehler zu isolieren. supervisorScope ermöglicht die Fortsetzung der übrigen async-Coroutinen, selbst wenn eine fehlschlägt — nützlich für nicht kritische Operationen.

Häufig gestellte Fragen

Kann async ohne await verwendet werden?

Ja, aber es ist sinnlos. async ohne await() startet eine Coroutine, deren Ergebnis jedoch verloren geht. Wenn das Ergebnis nicht benötigt wird, verwenden Sie launch — es erstellt kein Deferred und ist speicher- und leistungseffizienter.

Wie behandelt async Ausnahmen?

Eine Ausnahme innerhalb von async wird in Deferred gespeichert. Der Aufruf von await() löst diese Ausnahme aus. Zur Überprüfung ohne Auslösen verwenden Sie getCompletionExceptionOrNull(). Bei Verwendung von coroutineScope bricht ein Fehler alle untergeordneten Coroutinen ab.

Was ist awaitAll in Kotlin Coroutines?

awaitAll() — eine Erweiterungsfunktion für Iterable<Deferred<T>>, die die Coroutine anhält, bis alle Deferreds abgeschlossen sind. Gibt eine Ergebnisliste zurück. Wenn mindestens ein Deferred fehlschlägt, wird die Ausnahme ausgelöst und die restlichen werden abgebrochen.

Wie unterscheidet sich async von GlobalScope.async?

Ja. async ist eine CoroutineScope-Erweiterungsfunktion, die an den Gültigkeitsbereich gebunden ist. GlobalScope.async erstellt eine Coroutine ohne Bindung an den Lebenszyklus — sie kann unbegrenzt ausgeführt werden. GlobalScope wird in Android aufgrund des Leckrisikos nicht empfohlen.

Wie viele async-Coroutinen können für parallele Anfragen gestartet werden?

Die Anzahl wird vom Dispatcher bestimmt: Dispatchers.IO unterstützt bis zu 64 gleichzeitige Threads, Dispatchers.Default — bis zur Anzahl der CPU-Kerne. Verwenden Sie für Massenvorgänge begrenzte Parallelität über Semaphore oder mapNotNull mit awaitAll.

Zusammenfassung

  • async — ein Coroutine Builder, der Deferred<T> für den asynchronen Ergebnisabruf zurückgibt
  • Deferred erbt Job und fügt die Methoden await(), getCompleted(), getCompletionExceptionOrNull() hinzu
  • Parallele Ausführung mit async reduziert die Gesamtzeit auf die Dauer der längsten Operation
  • awaitAll() — ein Dienstprogramm zum Warten auf alle Deferreds in einer Sammlung
  • coroutineScope — empfohlener Wrapper für eine Gruppe von async mit Abbruchgarantie
  • Verwenden Sie async nicht für Fire-and-Forget — verwenden Sie stattdessen launch
  • In Android wird async für paralleles Laden in ViewModel mit viewModelScope verwendet

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch