๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Kotlin

[2] Kotiln Coroutines - Cancelation / TimeOut

by ๋„์บ๋ฆฌ๐Ÿฑ 2021. 7. 26.
๋ฐ˜์‘ํ˜•

https://medium.com/@limgyumin/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BD%94%EB%A3%A8%ED%8B%B4%EC%9D%98-%EA%B8%B0%EC%B4%88-cac60d4d621b

๋„์›€์ด ๋งŽ์ด ๋˜์—ˆ๋‹ค. 

 

์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด์˜ ๊ธฐ์ดˆ

์ฝ”ํ‹€๋ฆฐ ์˜ ์ฝ”๋ฃจํ‹ด์€ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ฒ˜๋ฆฌํ• ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

medium.com

 

Dispatcher

 

 

Ref.

Youtube :  [์ƒˆ์ฐจ์›, ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด] https://youtube.com/playlist?list=PLbJr8hAHHCP5N6Lsot8SAnC28SoxwAU5A

Ref : https://kotlinlang.org/

 

 

 

 

Cancelation

์‹คํ–‰ ํ–ˆ๋˜ ์ฝ”๋ฃจํ‹ด์„ ์ทจ์†Œ ํ•˜๋Š” ๋ฐฉ๋ฒ• → ์ทจ์†Œ ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ ์ด์œ ๋Š” ํ•˜๋‚˜ํ•˜๋‚˜ ๋ฉ”๋ชจ๋ฆฌ์™€ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐจ์ง€ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ

 ์ฝ”๋ฃจํ‹ด ์ทจ์†Œ์˜ ์กฐ๊ฑด
1) Cancel ํ˜ธ์ถœ
2) ์ฝ”๋ฃจํ‹ด ์ž์ฒด๊ฐ€ ์ทจ์†Œ์— ๋Œ€ํ•ด ํ˜‘์กฐ์ ์ธ ์ƒํƒœ๋กœ ๊ตฌํ˜„๋˜์–ด์žˆ์–ด์•ผํ•จ.

// ๋‹จ์ˆœ ์ฝ”๋ฃจํ‹ด ์ทจ์†Œ
// job ๊ฐ์ฒด๋Š” ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ฝ”๋ฃจํ‹ด์„ ์ทจ์†Œํ•˜๊ฒŒ๋„ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ
fun main() = runBlocking{
    //  ์ด ์ฝ”๋ฃจํ‹ด์€ 1000๋ฒˆ์„ ๋Œ๋ฉด์„œ 0.5์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ ์ˆซ์ž๋ฅผ ์ถœ
    val job = launch {
        repeat(1000){
            println("job: I'm sleeping ${it}...")
            delay(500L) //suspend func
        }
    }

    delay(1300L)
    println("main : I'm Tired of waiting")
    job.cancel() // 1.3์ดˆ ์ •๋„ ์ง€๋‚˜๋ฉด ์ด APP ์ด ๋๋‚ฌ์œผ๋ฉด ์ข‹๊ฒ ์Œ.
    job.join()
    println("main : Now i can quit.")
}

 

 

/ ์ฝ”๋ฃจํ‹ด ์ทจ์†Œ์˜ ์กฐ๊ฑด - supending functions ์€ ์ทจ์†Œ ๊ฐ€๋Šฅํ•˜๋‹ค.
// suspend ํ•จ์ˆ˜๋ฅผ ํ•˜๋‚˜๋ผ๋„ ๋‘์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น ์ฝ”๋ฃจํ‹ด์€ ์‹คํ–‰ ์ทจ์†Œ ํ•  ์ˆ˜ ์—†๋‹ค.
fun main() = runBlocking {
    val startTime = System.currentTimeMillis()
    val job = launch(Dispatchers.Default){
        var nextPrintTime = startTime
        var i = 0
        while(i < 5){
            if (System.currentTimeMillis() >= nextPrintTime){
                 yield() // suspend func : ๋”œ๋ ˆ์ด๋ฅผ ์ฃผ์ง€ ์•Š๊ณ ๋„ ์ข…๋ฃŒ๋ฅผ ์ฒดํฌ ํ•  ์ˆ˜ ์žˆ์Œ
                // delay(1L)  suspend func ์ด ๋ฐ˜๋“œ์‹œ
                println("job: I'm sleeping ${i++}...")
                nextPrintTime += 500L
            }
        }
    }
    delay(1300L)
    println("main : I'm tired of waiting")
    job.cancelAndJoin() // cancel ๊ณผ join ์„ ์ˆœ์ฐจ์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์ฃผ๋Š” ํ•จ์ˆ˜
    // cancel ๋˜์„œ ์ผ์‹œ ์ค‘๋‹จ ํ•จ์ˆ˜(yield ๋‚˜ delay)์• ์„œ ์ผ์‹œ ์ค‘๋‹จ์ด ๋˜์—ˆ๋‹ค๊ฐ€ ์žฌ๊ฐœ ๋ ๋•Œ, exception์„ ๋˜์ง„๋‹ค.
    println("main : Now i can quit")
}

 

 

 

 

isActive

// ์ฝ”๋ฃจํ‹ด์ด ์ทจ์†Œ ๋˜๊ธฐ ์œ„ํ•ด์„œ ํ˜‘์กฐ์ ์ธ ๋ฐฉ๋ฒ•์„ ์ทจํ•˜๋Š”๋ฐ ํฌ๊ฒŒ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๋ฐ 2๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€?
// ( ์ฒซ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ์œ„์—์„œ ๋ดค๋–ค ์ฃผ๊ธฐ์ ์œผ๋กœ suspending ํ˜ธ์ถœํ•ด๋ผ / ๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ๋ช…์‹œ์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ์ฒดํฌ ํ•˜์—ฌ _isActive_๋กœ)
// isActive : CourouineScope์˜ Boolean ๊ฐ’
// exception ์„ ๋˜์ง€์ง€๋Š” ์•Š๋Š”๋‹ค.
fun main() = runBlocking {

    val startTime = System.currentTimeMillis()

    val job = launch(Dispatchers.Default){
        var nextPrintTime = startTime
        var i = 0
        while(isActive){
            if(System.currentTimeMillis() >= nextPrintTime){
                println("job : I'm Sleeping ${i++} ..")
                nextPrintTime +=500L
            }
        }
    }

    delay(1300L)
    println("main : Tired waiting")
    job.cancelAndJoin()
    println("main : Now I can quit")
}

 

 

finally

: ๋„คํŠธ์›Œํฌ๋‚˜ DB ์“ฐ๋‹ค๊ฐ€ ๊ฐ‘์ž๊ธฐ ์ฝ”๋ฃจํ‹ด ์บ”์Šฌ ๋˜๋Š” ๋“ฑ์˜ ์ผ์ด ์žˆ์„ ๋•Œ, ๋‹ซ์•„์ฃผ๋Š” ์œ„์น˜

// ์ฝ”๋ฃจํ‹ด์„ ์ข…๋ฃŒํ•  ๋•Œ, ์–ด๋–ป๊ฒŒ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œ ํ•˜์—ฌ ์ค„ ์ˆ˜ ์žˆ๋Š”๊ฐ€?
// ๋„คํŠธ์›Œํฌ๋‚˜ DB๋ฅผ ์“ฐ๋‹ค๊ฐ€ ๊ฐ‘์ž๊ธฐ ์ฝ”๋ฃจํ‹ด cancel ๋˜๋ฉด ์ด ํŒŒ์ผ์„ ๋‹ซ์•„์ฃผ๊ณ  ๊ฐ€์•ผ ํ•˜๋Š”๋ฐ, ์ด ๋‹ซ์•„์ฃผ๋Š” ์œ„์น˜๊ฐ€ ์–ด๋””์ธ๊ฐ€? ๋‹ซ์•„์ฃผ๋Š” ๊ฑด finally
fun main() = runBlocking {

    val job = launch(Dispatchers.Default){
       try{
           repeat(1000){
               i -> println("job: I'm sleeping ${i} ...")
               val curTime  = System.currentTimeMillis() // 1970๋…„ 1/1์ผ ๋ถ€ํ„ฐ ๊ฒฝ๊ณผํ•œ ์‹œ๊ฐ„์„ long ๊ฐ’์œผ๋กœ ๋ฆฌํ„ดํ•จ
               val  timeFormat:SimpleDateFormat =  SimpleDateFormat("yyyy-mm-dd hh:mm:ss")
               val str = timeFormat.format(Date(curTime))
               println(str)
               println(Date(curTime))
               println()
               delay(500L) // ์ทจ์†Œ์— ํ˜‘์กฐ์ ์œผ๋กœ ๊ตฌํ˜„์ด ๋˜์–ด์žˆ์Œ
           }
       }finally {
           // ๋ฆฌ์†Œ์Šค ํ•ด์ œ ์ง€์—ญ
           println("job: i'm runnig finally")
       }
    }

    delay(1300L)
    println("main : Tired waiting")
    job.cancelAndJoin() // ์ผ์‹œ ์ค‘๋‹จ ๋˜์—ˆ๋‹ค๊ฐ€ ์žฌ๊ฐœ ๋  ๋•Œ, exception์„ ๋˜์งˆ ๋•Œ finally ๋ธ”๋ก์—์„œ ๋ฆฌ์†Œ์Šค ํ•ด์ œ๋ฅผ ํ•ด๋ผ.
    println("main : Now I can quit")
}

 

Timeout

// Timeout
// ์ฝ”๋ฃจํ‹ด์ด ์‹œ์ž‘๋  ๋•Œ, ์ด ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์ด ์ฝ”๋ฃจํ‹ด์€ ์ทจ์†Œ ๋œ๋‹ค. ๋ฏธ๋ฆฌ ํƒ€์ž„ ์•„์›ƒ์„ ์ง€์ •ํ•˜๋Š” ๋ฐฉ์‹
// withTimeout์„ ์“ฐ๋ฉด TimeoutCancellationException ์ด ๋‚˜๋Š”๋ฐ,
// withTimeoutOrNull ์ด๋ฉด Exception๋‚ฌ์„ ๋•Œ, ๊ฒฐ๊ณผ ๊ฐ’์ด null๋กœ ๋–จ์–ด์ง.

fun main() = runBlocking {
    val result = withTimeoutOrNull(2000L){
        repeat(1000){
            i -> println("i'm sleeping ${i}..")
            delay(500L)
        }
        "Done"
    }
    println("Result is ${result}")
}
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€