Kotlin/포스팅

코틀린 액터

짜집퍼박사(짜박) 2024. 1. 10. 01:00

코틀린 액터(Actor)는 동시성 프로그래밍에서 메시지 전달을 통해 통신하는 경량의 프로세스를 나타내는 개념입니다. 각 액터는 독립적으로 실행되며, 다른 액터와 메시지를 주고받아 상태를 변경하거나 작업을 수행합니다. 액터는 고루틴을 기반으로 하며, 메시지 처리는 비동기적으로 이루어집니다.

코틀린에서는 actor 빌더를 사용하여 액터를 생성할 수 있습니다. 액터는 Channel을 사용하여 메시지를 주고받습니다.

 

1. 기본적인 액터 예제

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor

sealed class Message
data class Greet(val name: String) : Message()
data class Thank(val from: String) : Message()

fun CoroutineScope.greeterActor() = actor<Message> {
    for (msg in channel) {
        when (msg) {
            is Greet -> println("Hello, ${msg.name}!")
            is Thank -> println("Thanks, ${msg.from}!")
        }
    }
}

fun main() = runBlocking {
    val actor = greeterActor()

    actor.send(Greet("Alice"))
    actor.send(Thank("Bob"))

    // Give some time for messages to be processed
    delay(100)

    actor.close()
}

위의 예제에서 greeterActor 함수는 액터를 생성하고, 해당 액터는 Message 클래스를 사용하여 Greet 또는 Thank 메시지를 처리하며 메시지에 따라 다르게 동작합니다.

 

2. 액터의 상태

액터는 내부적으로 상태를 가질 수 있으며, 메시지를 통해 상태를 변경하거나 새로운 상태를 생성할 수 있습니다.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor

sealed class CounterMessage
object IncrementCounter : CounterMessage()
class GetCounter(val response: CompletableDeferred<Int>) : CounterMessage()

fun CoroutineScope.counterActor() = actor<CounterMessage> {
    var counter = 0
    for (msg in channel) {
        when (msg) {
            is IncrementCounter -> counter++
            is GetCounter -> msg.response.complete(counter)
        }
    }
}

fun main() = runBlocking {
    val counter = counterActor()

    counter.send(IncrementCounter)
    counter.send(IncrementCounter)

    val response = CompletableDeferred<Int>()
    counter.send(GetCounter(response))

    println("Counter: ${response.await()}")

    counter.close()
}

위의 예제에서 counterActor 함수는 CounterMessage를 사용하여 액터를 생성하고, 해당 액터는 메시지에 따라 카운터를 증가시키거나 현재 카운터 값을 반환합니다.

 

3. 액터의 동작 제한

액터는 기본적으로 단일 스레드에서 실행되지만, 필요에 따라 다른 디스패처를 사용하여 다중 스레드에서 실행되도록 구성할 수 있습니다.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor

sealed class Message
data class Greet(val name: String) : Message()
data class Thank(val from: String) : Message()

fun CoroutineScope.greeterActor() = actor<Message>(Dispatchers.Default) {
    for (msg in channel) {
        when (msg) {
            is Greet -> println("Hello, ${msg.name} from ${Thread.currentThread().name}")
            is Thank -> println("Thanks, ${msg.from} from ${Thread.currentThread().name}")
        }
    }
}

fun main() = runBlocking {
    val actor = greeterActor()

    actor.send(Greet("Alice"))
    actor.send(Thank("Bob"))

    // Give some time for messages to be processed
    delay(100)

    actor.close()
}

위의 예제에서 greeterActor 함수는 Dispatchers.Default 디스패처를 사용하여 액터를 생성하며, 이로 인해 액터는 다중 스레드에서 실행될 수 있습니다.

액터는 비동기 프로그래밍에서 메시지 전달을 통한 효과적인 통신 패턴을 제공합니다. 메시지를 통해 독립적으로 동작하는 액터들은 공유 상태에 대한 동기화를 피하고 동시성 환경에서 안전하게 작업할 수 있도록 도와줍니다.

 

With ChatGPT

'Kotlin > 포스팅' 카테고리의 다른 글

코틀린 동기화와 락  (0) 2024.01.10
코틀린 자바 동시성 사용  (0) 2024.01.10
코틀린 티커  (0) 2024.01.10
코틀린 동시성 생산자  (0) 2024.01.10
코틀린 동시성 채널  (0) 2024.01.10