Kotlin协程-取消与超时

1.Job:取消协程 【类似于线程的cancle、 join】

suspend fun main(args: Array) {

    var job = GlobalScope.launch {
        repeat(1000, {
            println(it)
            delay(500)
        })
    }
    delay(1300)
    println("main start ")

    job.cancel()  // 取消 
    job.join()  //等待job执行完以后

 // job.cancelAndJoin()  将上面两个合二为一

    println("main end ")
}

result:
0
1
2
main start 
main end 

 一般都在finally 中释放资源

suspend fun main(args: Array) {

    var job = GlobalScope.launch {
        try {
            repeat(1000) { i ->
                println("job: I'm sleeping $i ...")
                delay(500L)
            }
        } finally {
           println("释放资源")
        }
    }
    delay(1300)
    println("main start ")
    job.cancelAndJoin()
    println("main end ")
}
result:
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main start 
释放资源
main end 

这里存在一个问题,在finally中如果调用挂起函数(suspend修饰的函数)会抛出异常

suspend fun main(args: Array) {

    var job = GlobalScope.launch {
        try {
            repeat(1000) { i ->
                println("job: I'm sleeping $i ...")
                delay(500L)
            }
        } finally {
            try {
                delay(1000)  //挂起函数
            } catch (e: Exception) {
                println(e)
            }
        }
    }
    delay(1300)
    println("main start ")
    job.cancelAndJoin()
    println("main end ")
}

result:
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main start 
kotlinx.coroutines.JobCancellationException: Job was cancelled; job=StandaloneCoroutine{Cancelling}@20d8d1ae
main end 

解决方案:withContext

suspend fun main(args: Array) {
    var job = GlobalScope.launch {
        try {
            repeat(1000) { i ->
                println("job: I'm sleeping $i ...")
                delay(500L)
            }
        } finally {
            withContext(NonCancellable) {
                println("job: I'm running finally")
                delay(1000L)
                println("job: And I've just delayed for 1 sec because I'm non-cancellable")
            }
        }
    }
    delay(1300)
    println("main start ")
    job.cancelAndJoin()
    println("main end ")
}
result:
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main start 
job: I'm running finally
job: And I've just delayed for 1 sec because I'm non-cancellable
main end 

2.超时:withTimeout  withTimeoutOrNull



//withTimeout
suspend fun main(args: Array) {
    withTimeout(1500,{
        repeat(1000) { i ->
            println("job: I'm sleeping $i ...")
            delay(500L)
        }
    })
    println("main end ")
}

result:
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1500 ms
	at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:124)
	at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:90)
	at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.kt:307)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.kt:116)
	at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:68)
	at java.lang.Thread.run(Thread.java:745)

//withTimeoutOrNull
suspend fun main(args: Array) {
    var c = withTimeoutOrNull(1500,{
        repeat(1000) { i ->
            println("job: I'm sleeping $i ...")
            delay(500L)
        }
    })
    println(c) //返回null
    println("main end ")
}
result:
job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
null
main end

 

你可能感兴趣的:(kotlin)