동시성 처리는 되게 많이 쓰이는 방법이여서
리액티브 프로그래밍, 쓰레드, 코루틴 정도가 대표적이지만
쓰기도 간단하고 비용도 적게드는 코루틴이 진짜 대박인것 같아서
코루틴에 대하여 공부를 하였습니다.
코루틴은 C#에서 처음 접해봐서 개념자체는 대략적으로 알고있었습니다.
코틀린이 동기적으로 코드를 짤수있는 이유 (내부적인 구조 : FSM) 등
여러 원리가 있지만 간단한 개념을 살펴보도록 하겠습니다.
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x.x'
코틀린을 사용하여면 의존성을 추가해야합니다.
원하는 버전으로 추가를 하시면 됩니다. (gradle 기준)
메인루틴 -> 코루틴
이런식으로 빠져나가 비동기 식으로 작동이 된다고 합니다.
GlobalScope
: 프로그램 어디서나 제어, 동작이 가능한 기본 범위
CoroutineScope
: 특정한 목적의 Dispatcher를 지정하여 제어 및 동작이 가능한 범위
Dispatchers.Default
: 기본적인 백그라운드 동작Dispatchers.IO
: I/O에 최적화 된 동작Dispatchers.Main
: 메인(UI) 스레드에서 동작Dispatchers
는 모든 플랫폼에서 지원되지 않음코루틴 생성에는 launch
,async
존재하는데
먼저 launch
를 살펴보자면
launch
: 반환값이 없는 Job객체
println("Start")
GlobalScope.launch {
// 만약 3초를 기다린다고 가정하면 Hello는 출력안됨 (메인 쓰레드가 먼저 종료되므로)
delay(1000) // 쓰레드가 아닌 코루틴 동작 일시 정지
println("Hello")
}
Thread.sleep(2000) // Thread 자체를 중단
println("Stop")
만약 GlobalScope
안에 delay
가 3초라면 "Hello"
는 출력이 되지 못하고
프로그램이 종료될것입니다.
이유는 메인쓰레드가 먼저 종료가 되어 코루틴이 실행을 못하게 되버립니다.
async
: 반환값이 존재하는 Deferred 객체
val deferred = (1..100).map { n ->
GlobalScope.async {
n
}
}
runBlocking {
val sum = deferred.map {
println(it.await().toLong())
it.await().toLong()
}.sum()
println(sum)
}
await()
: 코루틴의 결과를 반환하는 Deferred<T>
값을 반환합니다. 또한 값이 반환될때까지 대기합니다. (Deferred
의 실행이 끝날때까지 대기)
runBlocking {}
: 코루틴이 전부 실행될때까지 메인루틴(현재 스레드)을 잠시 대기시켜줌
fun main(args : Array<String>) {
// suspend 함수는 코루틴에서 호출 가능 하고 함수 내부에서는 비동기 코드 작동가능
GlobalScope.launch {
var k = workload(100)
print(k)
}
// 코루틴이 전부 수행되기전에 메인 쓰레드가 종료되서 출력못하는 상황을 방지하는 용도
runBlocking {
delay(2000)
}
}
suspend fun workload(n : Int) : Int {
delay(1000)
return n
}
suspend
: 함수 내부에서 비동기를 작동 가능하게함, 외부 코루틴 Block 에서 호출가능.
runBlocking {
var result = withTimeoutOrNull(50) {
for(i in 1..10) {
println(i)
delay(10)
}
"Finish"
}
println(result)
}
withTimeoutOrNull
: blocking 함수, 수행시간 내에 전부 수행하지 못하면 null을 반환함.
cancle()
함수로 코루틴 실행 취소 가능.
Job.join()
으로 Job
의 실행이 끝날때까지 대기하는 함수
코루틴은 다양한 기능들을 제공하고 있으므로
프로젝트를 진행하면서 필요한 기능을 하나씩 공부해나가는 방향으로 배워야 할것 같습니다.
위에서는 없지만 코틀린은
async
await
을 이용하여 동기적으로 코드를 작성한다는 것이 너무 편했다.