프로그래밍 놀이터/Kotlin, Coroutine

[Kotlin] Coroutines tutorial - async code 쉽게 짜기

돼지왕 왕돼지 2018. 11. 25. 13:30
반응형

[Kotlin] Coroutines tutorial - async code 쉽게 짜기


https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md



-

Kotlin coroutines 는 async code 를 sync code 의 구조를 바꾸지 않고 짤 수 있게 도와준다.




Coroutine Basics - modified

내용이 바뀌어서 새로 정리하였습니다. -> Coroutine Basics ( 코루틴 기초 )



예전 기록을 보고 싶으시면 아래 "더보기" 버튼을 눌러주세요!





Cancellation and timeouts - modified

내용이 바뀌어서 새로 정리하였습니다. -> Cancellation and Timeouts ( 취소와 타임아웃 )




예전 기록을 보고 싶으시면 아래 "더보기" 버튼을 눌러주세요!




Composing suspending functions - modified

내용이 바뀌어서 새로 정리하였습니다. -> Composing Suspending Functions ( suspending 함수 만들기 )





예전 기록을 보고 싶으시면 아래 "더보기" 버튼을 눌러주세요!




Coroutine context and dispatchers - modified

내용이 바뀌어서 새로 정리하였습니다. -> [Coroutine] Coroutine context and dispatchers



예전 기록을 보고 싶으시면 아래 "더보기" 버튼을 눌러주세요!





Asynchronous Flow - new

따로 정리하였습니다 -> [coroutine] Asyncronous Flow






Exception handling and supervision - new

따로 정리하였습니다. -> [coroutine] Exception handling and supervision 





Channels - modified ( now not experimental! )

따로 정리하였습니다. -> [coroutine] Channels




예전 기록을 보고 싶으시면 아래 "더보기" 버튼을 눌러주세요!







Shared mutable state and concurrency - modified

따로 정리하였습니다. -> [coroutine] Shared mutable state and concurrency





예전 기록을 보고 싶으시면 아래 "더보기" 버튼을 눌러주세요!






Select expression - experimental (core 1.0.1 기준)


-

Select expression 은 여러개의 suspending function 들을 await 하고 그 중 먼저 끝나는 녀석을 선택할 수 있는 기능을 제공한다.



-

fun fizz(context:CoroutineContext) = produce<String>(context){

    while(true){

        delay(300)

        send(“Fizz”)

    }

}


fun buzz(context:CoroutineContext) = produce<String>(context){

    while(true){

        delay(500)

        send(“Buzz!”)

    }

}


suspend fun selectFizzBuzz(fizz:ReceiveChannel<String>, buzz:ReceiveChannel<String>){

    select<Unit>{

        fizz.onReceive{ value ->

            println(“fizz -> ‘$value’”)

        }

        buzz.onReceive{ value ->

            println(“buzz -> ‘$value’”)

        }

    }

}


val fizz = fizz(coroutineContext)

val buzz = buzz(coroutineContext)

repeat(7){

    selectFizzBuzz(fizz, buzz)

}

coroutineContext.cancelChildren()


/* 결과는..

fizz -> 'Fizz'

buzz -> 'Buzz!'

fizz -> 'Fizz'

fizz -> 'Fizz'

buzz -> 'Buzz!'

fizz -> 'Fizz'

buzz -> 'Buzz!’

*/



-

onReceive 는 channel 이 close 되거나 안쪽로직에서 Exception 이 나거나 하면 fail 한다.

그래서 이 대신 onReceiveOrNull 을 사용할 수 있다.

이 때는 channel 이 close 되면 value 로 null 값이 들어온다.



-

Select expression 은 onSend clause 를 가지고 있다.

이 녀석은 selection 의 biased 특성과 잘 어울린다.

fun produceNumbers(context:CoroutineContext, side:SendChannel<Int>) = produce<Int>(context){

    for(num in 1..10){

        delay(100)

        select<Unit>{

            onSend(num){ } // send to primary channel

            side.onSend(num){ } // send to side channel

        }

    }

}


val side = Channel<Int>()

launch(coroutineContext){

    side.consumeEach{ println(“Side channel has $it”) }

}

produceNumbers(coroutineContext, side).consumeEach{

    println(“Consuming $it”)

    delay(250)

}

println(“Done consuming”)

coroutineContext.cancelChildren()


/* 결과는..

Consuming 1

Side channel has 2

Side channel has 3

Consuming 4

Side channel has 5

Side channel has 6

Consuming 7

Side channel has 8

Side channel has 9

Consuming 10

Done consuming

*/



-

deferred value 는 onAwait clause 를 통해 선택할 수 있다.

fun asyncString(time:Int) = async{

    delay(time.toLong())

    “Waited for %time ms"

}


fun asyncStringsList():List<Deferred<String>>{

    val random = Random(3)

    return List(12){ asyncString(random.nextInt(1000)) }

}


val list = asyncStringList()

val result = select<String>{

    list.withIndex().forEach{ (index, deferred) ->

        deferred.onAwait { answer -> 

            “Deferred $index produced answer ‘$answer’”

        }

    }

}

println(result)

val countActive = list.count { it.isActive }

println(“$countActive coroutines are still active”)


/* 결과는.. ( 4, 128, 11 값 모두 상황에 따라 다를 수 있을 것 같다. )

Deferred 4 produced answer 'Waited for 128 ms'

11 coroutines are still active

*/




반응형