Actors und strukturierte Zustandsverwaltung
Verwenden Sie Actor-ähnliche Muster, um den Zustandszugriff in nebenläufigem Code zu serialisieren.
Actors und strukturierte Zustandsverwaltung ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.
Was ist ein Actor?
Ein Actor ist eine Coroutine, die privaten veränderlichen Zustand besitzt und über einen Channel kommuniziert. Externer Code greift niemals direkt auf diesen Zustand zu, sondern nur über Nachrichten.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
sealed class CounterMsg
object Increment : CounterMsg()
class GetCount(val response: CompletableDeferred<Int>) : CounterMsg()
fun CoroutineScope.counterActor() = actor<CounterMsg> {
var counter = 0
for (msg in channel) {
when (msg) {
is Increment -> counter++
is GetCount -> msg.response.complete(counter)
}
}
}Den Actor verwenden
Senden Sie Nachrichten mit send an den Actor. Der Actor verarbeitet sie nacheinander und serialisiert so den Zugriff auf den Zustand.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
// (CounterMsg sealed class from previous scene)
fun main() = runBlocking {
val counter = counterActor()
repeat(100) { counter.send(Increment) }
val response = CompletableDeferred<Int>()
counter.send(GetCount(response))
println("Count: ${response.await()}") // 100
counter.close()
}Actor ersetzt Mutex
Actors machen Mutexes überflüssig, indem sie den Zugriff auf den Zustand von vornherein sequenziell gestalten. Alle Änderungen finden innerhalb einer Coroutine statt.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
sealed class Msg
object Inc : Msg()
data class Get(val d: CompletableDeferred<Int>) : Msg()
fun CoroutineScope.safeCounter() = actor<Msg> {
var n = 0
for (m in channel) when(m) {
is Inc -> n++
is Get -> m.d.complete(n)
}
}
fun main() = runBlocking {
val a = safeCounter()
repeat(1000) { a.send(Inc) }
val d = CompletableDeferred<Int>()
a.send(Get(d))
println(d.await()) // 1000
a.close()
}Typisiertes Nachrichtenprotokoll
Definieren Sie Ihr Nachrichtenprotokoll als Hierarchie einer sealed class, damit es im when-Ausdruck des Actors vollständig behandelt werden kann.
sealed class BankMsg
data class Deposit(val amount: Double) : BankMsg()
data class Withdraw(val amount: Double, val result: CompletableDeferred<Boolean>) : BankMsg()
data class Balance(val result: CompletableDeferred<Double>) : BankMsg()
// Actor holds balance privately — outside code sends messages onlyZustandsautomat als Actor
Actors eignen sich natürlich als Zustandsautomaten: Interne Zustandsübergänge erfolgen als Reaktion auf Nachrichten atomar.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
enum class TrafficState { RED, GREEN, YELLOW }
fun CoroutineScope.trafficLight() = actor<Unit> {
var state = TrafficState.RED
for (msg in channel) {
state = when (state) {
TrafficState.RED -> TrafficState.GREEN
TrafficState.GREEN -> TrafficState.YELLOW
TrafficState.YELLOW -> TrafficState.RED
}
println("State: $state")
}
}
fun main() = runBlocking {
val light = trafficLight()
repeat(6) { light.send(Unit) }
light.close()
}actor()-Builder
Der Coroutine-Builder actor { } erstellt einen Actor mit einem Channel als Eingangspuffer. Der Actor ist eine Coroutine, die Nachrichten aus dem channel verarbeitet.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun CoroutineScope.logActor() = actor<String>(capacity = Channel.BUFFERED) {
val log = mutableListOf<String>()
for (msg in channel) {
log.add(msg)
println("[LOG] $msg")
}
println("Log entries: ${log.size}")
}
fun main() = runBlocking {
val logger = logActor()
repeat(5) { logger.send("Event $it") }
logger.close()
// actor finishes after close
}Einen Actor stoppen
Schließen Sie den Sendekanal des Actors mit close(). Die for-Schleife im Actor endet, sodass vor Abschluss der Coroutine noch Aufräumarbeiten ausgeführt werden können.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val actor = actor<String> {
for (msg in channel) println("Got: $msg")
println("Actor done")
}
actor.send("hello")
actor.send("world")
actor.close()
// Wait for actor to finish
delay(50)
}Actors mit Backpressure
Setzen Sie die Kapazität des Channels des Actors, um Backpressure anzuwenden – Sender werden angehalten, wenn der Eingangspuffer voll ist.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun CoroutineScope.slowProcessor() = actor<Int>(capacity = 2) {
for (item in channel) {
delay(100) // slow processing
println("Processed: $item")
}
}
fun main() = runBlocking {
val proc = slowProcessor()
repeat(5) { proc.send(it) } // sender suspends when capacity full
proc.close()
}Actor vs. Mutex: Performance
Actors serialisieren den Zugriff ohne Lock-Contention und eignen sich für komplexe Zustände mit mehreren Nachrichtentypen. Mutex ist für einen einzelnen gemeinsam genutzten Zähler einfacher, aber weniger gut kombinierbar.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
// For a simple counter: Mutex is fine
val mutex = Mutex()
var simpleCounter = 0
// For complex state + multiple operations: Actor is cleaner
// Actor: messages describe intent; state changes are encapsulated
fun main() = runBlocking { println("Choose based on state complexity") }CompletableDeferred für Anfrage-Antwort
Für Anfrage-Antwort-Muster innerhalb eines Actors fügen Sie eine CompletableDeferred in die Nachricht ein. Der Actor schließt sie ab, und der Sender wartet mit await auf das Ergebnis.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
data class Query(val key: String, val reply: CompletableDeferred<String?>)
fun CoroutineScope.cacheActor() = actor<Any> {
val cache = mutableMapOf<String, String>()
for (msg in channel) when (msg) {
is Pair<*, *> -> cache[msg.first as String] = msg.second as String
is Query -> msg.reply.complete(cache[msg.key])
}
}Moderne Alternative: StateFlow + coroutineScope
Der Builder actor ist experimentell und wird möglicherweise als veraltet markiert. Die moderne Alternative ist eine ViewModel- oder Service-Klasse mit einem MutableStateFlow, das aus einer einzelnen Coroutine aktualisiert wird.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
class CounterService(scope: CoroutineScope) {
private val _count = MutableStateFlow(0)
val count = _count.asStateFlow()
private val events = kotlinx.coroutines.channels.Channel<Unit>()
init {
scope.launch {
for (e in events) _count.value++
}
}
fun increment() { events.trySend(Unit) }
}Kurzer Check
Wie stellen Actors einen sicheren gleichzeitigen Zugriff auf den Zustand sicher?
Zusammenfassung
Actors kapseln veränderlichen Zustand in einer einzelnen Coroutine und stellen Operationen als typisierte Channel-Nachrichten bereit. Sie serialisieren den Zugriff auf natürliche Weise, unterstützen Zustandsautomaten und vermeiden Lock-Contention – auf Kosten einer zusätzlichen Indirektion durch die Nachrichtenübermittlung.
Lerne Kotlin mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 51
- Lektionen
- 203
Häufig gestellte Fragen
Ist die Lektion „Actors und strukturierte Zustandsverwaltung“ kostenlos?
Ja — der vollständige Text von „Actors und strukturierte Zustandsverwaltung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Actors und strukturierte Zustandsverwaltung“?
Verwenden Sie Actor-ähnliche Muster, um den Zustandszugriff in nebenläufigem Code zu serialisieren. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Kotlin Academy zu starten?
Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Actors und strukturierte Zustandsverwaltung“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?
Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Channel-Grundlagen: send, receive und close
- Channel-Typen: Rendezvous, Buffered, Conflated, Unlimited
- Mutex und Semaphore für gemeinsam genutzten Zustand
- Actors und strukturierte Zustandsverwaltung