Foggy day

Kotlin - Coroutine concorrency example 본문

Kotlin

Kotlin - Coroutine concorrency example

jinhan38 2021. 4. 12. 00:39

 

코루틴의 순차적, 동시적 작업들을 컨트롤 할 수 있게 해주는 것이 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