Foggy day
Kotlin - Coroutine concorrency example 본문
코루틴의 순차적, 동시적 작업들을 컨트롤 할 수 있게 해주는 것이 Defferd 객체인데 이는 JOB을 상속받았다.
1. 코루틴 순차적 실행
class KotlinPlayGroundActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin_play_ground)
//코루틴은 비동기일지라도 순차적으로 실행된다.
//예를 들어 firstFunction과 secondFunction 함수가 retrofit 호출일지라도
//먼저 실행한 firstFunction 함수의 콜백이 도달해서 완전히 끝나고 난 후에 secondFunction 함수가 호출된다
// MainThread에서 실행해도 UI에 Blocking 현상이 전혀 발생하지 않는다.
// 만약에 runBlockingscope로 실행하면 모든 작업이 끝날때까지 UI가 정지된다.
// launch를 실행한다는 것은 새로운 코루틴을 만드는 것이다.
GlobalScope.launch {
val time = measureTimeMillis {
val first = firstFunction()
print("$first")
val second = secondFunction()
print("$second")
print("더한 값 : ${first + second}")
}
print("걸린 시간 : $time")
}
}
private suspend fun firstFunction(): Int {
print("firstFunction 진입")
delay(2000)
print("firstFunction 2초 경과")
return 20
}
private suspend fun secondFunction(): Int {
print("secondFunction 진입")
delay(3000)
print("secondFunction 3초 경과")
return 30
}
fun print(msg: String) {
println("Kotlin text : $msg")
}
}
2. 코루틴 동시 실행
class KotlinPlayGroundActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin_play_ground)
//async로 작업을 호출하면 기존의 비동기 방식처럼 작동한다.
//firstFunction 함수가 끝날 때 까지 기다리는 것이 아니라
//실행시키고 다음 줄로 넘어가서 secondFunction 함수를 실행시킨다.
GlobalScope.launch {
val time = measureTimeMillis {
val first = async { firstFunction() }
print("$first")
val second = async { secondFunction() }
print("$second")
// await를 붙이면 first와 second의 작업이 끝나기를 기다리고, 작업이 다 끝나면 덧셈을 한다.
print("더한 값 : ${first.await() + second.await()}")
}
print("걸린 시간 : $time")
}
}
private suspend fun firstFunction(): Int {
print("firstFunction 진입")
delay(2000)
print("firstFunction 2초 경과")
return 20
}
private suspend fun secondFunction(): Int {
print("secondFunction 진입")
delay(3000)
print("secondFunction 3초 경과")
return 30
}
fun print(msg: String) {
println("Kotlin text : $msg")
}
}
3. Lazily started async
class KotlinPlayGroundActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin_play_ground)
//async(start = CoroutineStart.LAZY) 이용해 호출하면 해당 함수를 start 혹은 await 했을 때 작업을 시작한다.
// start와 await의 차이점이 있다.
//start로 작업을 시작하면 동시성 실행이며 await로 작업을 실행하면 순차적 실행이다.
GlobalScope.launch {
val time = measureTimeMillis {
val first = async(start = CoroutineStart.LAZY) { firstFunction() }
val second = async(start = CoroutineStart.LAZY) { secondFunction() }
first.start()
second.start()
print("더한 값 : ${first.await() + second.await()}")
}
print("걸린 시간 : $time")
}
}
private suspend fun firstFunction(): Int {
print("firstFunction 진입")
delay(2000)
print("firstFunction 2초 경과")
return 20
}
private suspend fun secondFunction(): Int {
print("secondFunction 진입")
delay(3000)
print("secondFunction 3초 경과")
return 30
}
fun print(msg: String) {
println("Kotlin text : $msg")
}
}
start로 async를 실행시켰기 때문에 3초의 시간이 걸렸다.
class KotlinPlayGroundActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin_play_ground)
//async(start = CoroutineStart.LAZY) 이용해 호출하면 해당 함수를 start 혹은 await 했을 때 작업을 시작한다.
// start와 await의 차이점이 있다.
//start로 작업을 시작하면 동시성 실행이며 await로 작업을 실행하면 순차적 실행이다.
GlobalScope.launch {
val time = measureTimeMillis {
val first = async(start = CoroutineStart.LAZY) { firstFunction() }
val second = async(start = CoroutineStart.LAZY) { secondFunction() }
print("더한 값 : ${first.await() + second.await()}")
}
print("걸린 시간 : $time")
}
}
......
}
await으로 작업을 실행시켰더니 5초가 걸렸다.
4. async with structured concurrency about exception
class KotlinPlayGroundActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin_play_ground)
GlobalScope.launch(Dispatchers.Default) {
//time을 호출하지 않아도 concurrentSum 함수는 실행된다.
//measureTimeMillis 는 시간을 측정하기 위해서만 사용된다.
val time = measureTimeMillis {
print("${concurrentSum()}")
}
print("걸린 시간 : $time")
}
}
private suspend fun concurrentSum(): Int = coroutineScope {
val first = async { firstFunction() }
val second = async { secondFunction() }
//coroutineScope 안에서 Exception이 발생하면 작업중인 코루틴들이 모두 종료된다.
//이러한 structured concurrency 형식으로 코루틴을 조합해서 사용하는 것이 안전하다.
throw Exception("에러 발생!!")
first.await() + second.await()
}
private suspend fun firstFunction(): Int {
print("firstFunction 진입")
delay(2000)
print("firstFunction 2초 경과")
return 20
}
private suspend fun secondFunction(): Int {
print("secondFunction 진입")
delay(3000)
print("secondFunction 3초 경과")
return 30
}
fun print(msg: String) {
println("Kotlin text : $msg")
}
}
5. Cancelation propagated coroutines hierarchy
class KotlinPlayGroundActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin_play_ground)
runBlocking {
try {
failedConcurrencySum()
} catch (e: ArithmeticException) {
print("ArithmeticException 발생함")
}
}
}
private suspend fun failedConcurrencySum(): Int = coroutineScope {
val one = async<Int> {
try {
print("첫번째 진입")
delay(2000)
100
} finally {
print("첫번째 one cancel -> finally")
}
}
val two = async<Int> {
delay(1000)
print("두번째 two throw exception")
throw ArithmeticException()
}
val three = async<Int> {
try {
print("세번째 진입")
delay(3000)
300
} finally {
print("세번째 three cancel -> finally")
}
}
val first = one.await()
val second = two.await()
val third = three.await()
first + second + third
}
fun print(msg: String) {
println("Kotlin test : $msg")
}
}
'Kotlin' 카테고리의 다른 글
Kotlin - Coroutine cancel (0) | 2021.04.10 |
---|---|
Kotlin - coroutine Scope basic (0) | 2021.04.10 |
Kotlin - data class destructuring (0) | 2021.04.08 |
Kotlin - Object Expressions (0) | 2021.04.08 |
Kotlin - when, for (0) | 2021.04.06 |