ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Kotlin ์ฝ”๋ฃจํ‹ด(Coroutines)์˜ Cancellation๊ณผ Timeouts
    ๐ŸณDev/Dev 2022. 7. 16. 16:39
    ์ƒˆ์ฐจ์›๋‹˜์˜ ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค

    1. Cancellation and Timeouts

    1. Cancel

    ์‹คํ–‰ํ•œ ์ฝ”๋ฃจํ‹ด์„ ์ค‘๋‹จํ•˜๋Š” ๋ฐฉ๋ฒ• : ๋ฐ”๋กœ cancel ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ๊ฐ€๋Šฅํ•˜๋‹ค!

    import kotlinx.coroutines.*
    
    fun main() =runBlocking{
        val job = launch{
            repeat(5) { i ->
                println("Coroutine A, $i")
                delay(500L)
            }
        }
    
        delay(1000L)
        println("tired")
        job.cancel()
        job.join()
        println("quit")
    }
    

     

    ํ•˜์ง€๋งŒ cancel๋„ ์ ์šฉ๋˜๋Š” ์กฐ๊ฑด์ด ์ฃผ์–ด์ง„๋‹ค.

    ์ผ๋‹จ ์ฝ”๋ฃจํ‹ด ์ฝ”๋“œ๊ฐ€ ํ˜‘์กฐ์ ์ผ ํ•„์š”๊ฐ€ ์žˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์งค ๋•Œ ์•„๋ž˜์˜ ์š”์†Œ๋“ค์„ ์ƒ๊ฐํ•˜๋ฉด์„œ ์งœ๋ณด์ž.

    • ์ฃผ๊ธฐ์ ์œผ๋กœ suspend ํ•จ์ˆ˜ ์‚ฌ์šฉ
      • suspend ํ•จ์ˆ˜๋Š” ์ทจ์†Œ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค
    • isActive ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ์ฒดํฌ

    1. suspend ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ cancel

    ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์˜๋„ํ•œ ๋Œ€๋กœ ์ข…๋ฃŒํ•˜์ง€ ์•Š๋Š”๋‹ค.

    import kotlinx.coroutines.*
    
    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){
    				println("Job : I am sleeping ${i++}")
            nextPrintTime += 500L
    			}
    		}
    	}
    	delay(1300L)
    	println("tired")
    	job.cancelAndJoin()
    	println("quit")
    }
    
    

     

    ์˜ค์ž‰? ์™œ ๊ทธ๋Ÿฌ์ง€

    ์ด๋Š” ๋ฐ”๋กœ, launch ๋‚ด๋ถ€์— suspend ํ•จ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค!

     

    ์ด๋Š” ์•„๋ž˜ ์ธํ…”๋ฆฌ์ œ์ด์—์„œ ๋” ์ž˜ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ๊ฐ€์žฅ ์™ผ์ชฝ์— ์ดˆ๋ก ๊ณก์„ ์ด ์žˆ๋Š” ํ™”์‚ดํ‘œ๊ฐ€ suspend ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

    ์œ„์˜ main์€ suspend ํ•จ์ˆ˜์ธ delay()๋ฅผ launch ํ•จ์ˆ˜ ์•ˆ์— ์‚ฌ์šฉํ–ˆ๊ณ , ์•„๋ž˜ main์€ ์ „ํ˜€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค.

     

    ๊ทธ๋ž˜์„œ ์œ„ main๊ณผ ๋‹ค๋ฅด๊ฒŒ ์•„๋ž˜ main์€ ์˜๋„ํ•œ ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค.

     

     

    ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด suspend ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š”๋ฐ,

    ์ด๋•Œ yield()๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

    yield๋Š” Exception๊ณผ ํ•จ๊ป˜ ๋ฐ˜ํ™˜๋˜์–ด, ์˜ˆ์™ธ๋ฅผ ๋ฐ›๊ณ  ์‹ถ๋‹ค๋ฉด try catch๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

     

    import kotlinx.coroutines.*
    
    fun main() =runBlocking{
    val startTime = System.currentTimeMillis()
    val job =launch(Dispatchers.Default){
    	try {
    		var nextPrintTime = startTime
        var i = 0
        while (i < 5) {
    	    if (System.currentTimeMillis() >= nextPrintTime) {
    	      yield()
    				println("Job : I am sleeping ${i++}")
            nextPrintTime += 500L
    			}
    	  }
    	} catch (e: Exception) {
    			println("Exception $e")
        }
    	}
    	delay(1300L)
    	println("tired")
      job.cancelAndJoin()
    	println("quit")
    }
    
    

    2. isActive ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ cancel

    ์ƒํƒœ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋„ cancel์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

    isActive ๋ณ€์ˆ˜๋Š” cancel()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด true์—์„œ false๋กœ ๋ฐ”๋€๋‹ค.

     

    import kotlinx.coroutines.*
    
    fun main() =runBlocking{
      val job =launch(Dispatchers.Default){
        var i = 0
          println("Before : isActive $isActive")
          while (isActive) {
              println("Job : I am sleeping ${i++}")
          }
          println("After : isActive $isActive")
      }
      delay(1L)
      println("tired")
      job.cancelAndJoin()
      println("quit")
    }
    

    3. Closing resources with finally

    ์ฝ”๋ฃจํ‹ด์„ ์ข…๋ฃŒํ•  ๋•Œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•˜๊ธฐ ์œ„ํ•ด try-finally ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•œ๋‹ค.

    import kotlinx.coroutines.*
    
    fun main() =runBlocking{
    	val job =launch{
    	try {
    		repeat(5){i->
    			println("Coroutine A, $i")
    			delay(500L)
    		}
    	} finally {
    		println("I am running finally")
    	  }
    	}
    
    	delay(1000L)
    	println("tired")
      job.cancelAndJoin()
    	println("quit")
    }
    

     

    4. Run non-cancellable bloc

    ์ทจ์†Œ ๋œ ์ฝ”๋ฃจํ‹ด ์•ˆ์—์„œ ์ฝ”๋ฃจํ‹ด์œผ๋กœ suspend ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, ์ฆ‰ finally ์•ˆ์—์„œ ์ฝ”๋ฃจํ‹ด์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒฝ์šฐ

    ๋„ ์—„์ฒญ ๋ ˆ์–ดํ•˜๊ฒŒ ์กด์žฌํ•œ๋‹ค.

    import kotlinx.coroutines.*
    
    fun main() =runBlocking{
    	val job =launch{
    		try {
    			repeat(5){i->
    				println("Coroutine A, $i")
    	      delay(500L)
    			}
    		} finally {
    		  withContext(NonCancellable){
    				println("Job : I am running finally")
    	      delay(1000L)
    				println("Job : and Just Delay")
    			}
    		}
    	}
    	delay(1000L)
    	println("tired")
    	job.cancelAndJoin()
    	println("quit")
    }
    

     

    2. Timeout

    cancel์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„, ์ •ํ•ด์ง„ ์‹œ๊ฐ„์ด ๋˜๋ฉด ์ฝ”๋ฃจํ‹ด์ด cancel๋˜๋Š” ๋งค์ง

    1. withTimeout

    import kotlinx.coroutines.*
    
    fun main() =runBlocking{
    	withTimeout(1300L){
    		repeat(100){i->
    			println("I am Sleeping, $i")
          delay(500L)
    		}
      }
    }
    

    ํ•˜์ง€๋งŒ ์ฝ”๋ฃจํ‹ด ์ข…๋ฃŒ์™€ ๋™์‹œ์— TimeoutCancellationException์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

    ์ด๋ฅผ ๋ณด์™„ํ•œ ๋ฐฉ๋ฒ•์ด Null์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ!

    2. withTimeoutOrNull

    import kotlinx.coroutines.*
    
    fun main() =runBlocking{
    	val result = withTimeoutOrNull(1300L){
    		repeat(100){i->
    			println("I am Sleeping, $i")
    	    delay(500L)
    		}
    	}
    	println("result id $result")
    }
    

    ์ด๋ ‡๊ฒŒ null์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ Timeout์ด ์‹คํ–‰๋˜์–ด ์ฝ”๋ฃจํ‹ด์ด ์ข…๋ฃŒ๊ฐ€ ๋œ๋‹ค.

     

     

    ์ฐธ์กฐ

     

    ์ƒˆ์ฐจ์›์˜ ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด(Coroutines) ๊ฐ•์ขŒ

    ์ƒˆ์ฐจ์›์˜ ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด(Coroutines) ๊ฐ•์ขŒ

    www.youtube.com

     

Designed by Tistory.