Actorit ja rakenteinen tilanhallinta
Käyttäkää actor-tyylisiä malleja tilan käytön sarjallistamiseen samanaikaisessa koodissa.
Actorit ja rakenteinen tilanhallinta on ilmainen Kotlin Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Kotlin Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Mikä on aktori
Aktori on korutiini, joka omistaa yksityisen muokattavan tilan ja viestii kanavan kautta. Ulkoinen koodi ei koskaan käytä tilaa suoraan, vaan ainoastaan viestien kautta.
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)
}
}
}Aktorin käyttäminen
Lähettäkää viestejä aktorille käyttämällä send-metodia. Aktori käsittelee viestit yksi kerrallaan ja sarjallistaa tilan käytön.
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()
}Aktori korvaa Mutexin
Aktori poistaa mutexien tarpeen tekemällä tilan käytöstä rakenteellisesti peräkkäistä. Kaikki muutokset tehdään yhden korutiinin sisällä.
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()
}Tyypitetty viestiprotokolla
Määritelkää viestiprotokolla sealed class -luokkahierarkiana, jotta kaikki tapaukset voidaan käsitellä aktorin when-lausekkeessa.
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 onlyTilakone aktorina
Aktori toimii luontevasti tilakoneena: sisäiset tilasiirtymät tapahtuvat atomisesti viestien seurauksena.
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()-rakentaja
actor { }-korutiinin rakentaja luo actorin, jonka viestipostilaatikkona toimii kanava. Actor on korutiini, joka käsittelee channel-kanavasta tulevia viestejä.
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
}Actorin pysäyttäminen
Sulje actorin lähetyskanava kutsumalla close()-metodia. Actorin for-silmukka päättyy, jolloin siivoustoimet voidaan suorittaa ennen korutiinin päättymistä.
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)
}Actorit ja backpressure
Määritä actorin kanavan kapasiteetti, jotta backpressure tulee käyttöön — lähettäjät keskeyttävät suorituksensa, kun postilaatikko on täynnä.
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()
}Actorin ja Mutexin suorituskyky
Actorit sarjoittavat käytön ilman lukituskilpailua ja sopivat monimutkaiseen tilaan, jossa on useita viestityyppejä. Mutex on yksinkertaisempi yhden jaetun laskurin tapauksessa, mutta sitä on vaikeampi yhdistellä.
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 pyyntö–vastausmallissa
Kun actorin sisällä käytetään pyyntö–vastausmallia, sisällytä viestiin CompletableDeferred. Actor täydentää sen, ja lähettäjä odottaa sen valmistumista.
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])
}
}Moderni vaihtoehto: StateFlow + coroutineScope
actor-rakentaja on kokeellinen, ja se saatetaan poistaa käytöstä. Moderni vaihtoehto on ViewModel- tai palveluluokka, joka päivittää MutableStateFlow-oliota yhdestä korutiinista.
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) }
}Pikakysymys
Miten actorit varmistavat tilan turvallisen samanaikaisen käytön?
Kertaus
Actorit kapseloivat muokattavan tilan yhteen korutiiniin ja tarjoavat toiminnot tyypitettyinä kanavaviesteinä. Ne sarjoittavat käytön luontevasti, tukevat tilakoneita ja poistavat lukituskilpailun — viestinvälityksen aiheuttaman ylimääräisen välikerroksen kustannuksella.
Opi Kotlin tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 51
- Oppitunnit
- 203
Usein kysytyt kysymykset
Onko oppitunti ”Actorit ja rakenteinen tilanhallinta” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Kotlin Academy-oppimispolun 3 oppituntia, myös oppitunnin “Actorit ja rakenteinen tilanhallinta”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Actorit ja rakenteinen tilanhallinta”?
Käyttäkää actor-tyylisiä malleja tilan käytön sarjallistamiseen samanaikaisessa koodissa. Harjoittelet Kotlin Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Kotlin Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Kotlin Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Actorit ja rakenteinen tilanhallinta”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Kotlin Academy-oppitunnilla?
Kyllä. Jokainen Kotlin Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Channelin perusteet: send, receive ja close
- Channel-tyypit: Rendezvous, Buffered, Conflated, Unlimited
- Mutex ja Semaphore jaetulle tilalle
- Actorit ja rakenteinen tilanhallinta