Skip to content

Instantly share code, notes, and snippets.

@posth2071
Last active May 1, 2024 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save posth2071/cbc3ad2cfc77906b2178c978dcf5ae88 to your computer and use it in GitHub Desktop.
Save posth2071/cbc3ad2cfc77906b2178c978dcf5ae88 to your computer and use it in GitHub Desktop.
코루틴빌더(CoroutineBuilder) Actor 사용 예시
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor
import kotlin.system.measureTimeMillis
/*
* Sealed Class CounterMsg 정의
* : Sealed class는 enum class의 확장판 개념 (enum은 상수들의 집합이라면 sealed는 클래스들의 집합)
* : Sealed Class는 모두 abstract(추상) 상태로 사용 시 구현이 필요
* : 내부 클래스는 sealed class를 상속(extends) 필수, CounterMsg()
* */
sealed class CounterMsg
object IncCounter : CounterMsg() // Object - 싱글톤 의미
class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // GetCounter클래스 (response 속성을 가짐)
fun main() {
runBlocking {
// 확장함수 counterActor() 호출 -> SendChannnel 반환 (counter = SendChannel)
val counter = counterActor()
GlobalScope.massiveRun { // 확장함수 massiveRun(), 인수가 action 하나뿐이라 소괄호'()' 생략 후 람다식으로 표현
counter.send(IncCounter) // massiveRun함수 내부에서 action() 호출 시 실행될 부분
}
// massiveRun이 끝난뒤 실행
val response = CompletableDeferred<Int>() // CompletableDeferred<Int>란 지연가능한 실행객체로 Int를 반환한다는 의미
counter.send(GetCounter(response)) // 채널을 통해 GetCounter(response)를 전송
println("Counter = ${response.await()}") // 결과값 대기 await()
counter.close() // 채널(Channel) 닫기, close() 호출하면 채널을 통해 특별한 닫힘토큰이 전송됨
}
}
// CoroutineScope 확장함수 선언, actor() 빌더 사용으로 SendChannel 인스턴스를 반환
fun CoroutineScope.counterActor() = actor<CounterMsg> {
// actor 블록 내에 속성들은 로컬(지역) 변수로 사용됨
var counter = 0
// actor{} 블록 내부는 수신자(Receiver) 역할로, 채널 전부 순회를 위한 for-loop문
for (msg in channel) {
// when을 이용해 채널을 통해 전송된 msg가 selaed Class 내부의 어떤 type인지 구분
when (msg) {
is IncCounter -> counter++ // abstract(구현), IncCounter 타입이면 counter++
is GetCounter -> msg.response.complete(counter) // GetCounter의 속성인 response의 값을 반환
// complete() 함수? CompletableDeferred<Int>는 지연실행 가능한 객체로 타입은 Int이다.
// complete()는 실행한다는 의미인데 int값을 반환한다는 걸로 이해하면 된다
}
}
}
// CoroutineScope 확장함수, 인수가 "action :suspend () -> Unit"으로 반환값이 없는 지연(suspend) 고차함수(high-order function)
suspend fun CoroutineScope.massiveRun(action: suspend () -> Unit) {
val n = 100 // 생성할 코루틴 개수, 로컬(지역) 변수
val k = 1000 // 각 코루틴에서 반복 실행할 횟수
val time = measureTimeMillis {
val jobs = List(n) { // List(100), 100개의 코루틴을 생성 반복
launch {
repeat(k) { // repeat(1000), 코루틴 1개당 1000번 반복 실행
action() // action 고차함수 실행
}
}
}
jobs.forEach { it.join() } // 100개의 코루틴(jobs)를 하나씩 join() 종료 대기
}
println("Completed ${n * k} actions in $time ms") // 코루틴이 모두 종료 되고나서 출력할 내용
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment