协程的取消与挂起

协程的基本取消

package cancel

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

/**
 * 一个用户也许关闭了一个启动了协程的界面,
 * 现在协程的执行结果已经不再被需要了,这时,它应该是可以被取消的
 */
fun main() = runBlocking {

    val job = launch {
        repeat(1000) { i ->
            println("this is i = $i")
            delay(500L)
        }
    }
    delay(1300L)
    println("main:waiting...")
    job.cancel() // 取消job
    job.join() // 等待job执行结束
    println("main:exiting...")

//    output:
//    this is i = 0
//    this is i = 1
//    this is i = 2
//    main:waiting...
//    main:exiting...

}

协程的cancelAndJoin

package cancel

import kotlinx.coroutines.*

/**
 * 协程的取消是 协作 的。一段协程代码必须协作才能被取消。
 * 所有 kotlinx.coroutines 中的挂起函数都是可被取消的 。
 * 它们检查协程的取消,并在取消时抛出 CancellationException。
 * 如果协程正在执行计算任务,并且没有检查取消的话,那么它是不能被取消的,
 */
fun main() = runBlocking {

    val startTime = System.currentTimeMillis()
    val job = launch(Dispatchers.Default) {
        var nextPrintTime = startTime
        var i = 0
        while (i < 5) { // 一个执行计算的循环,只是为了占用 CPU
            // 每秒打印消息两次
            if (System.currentTimeMillis() >= nextPrintTime) {
                println("job: I'm sleeping ${i++} ...")
                nextPrintTime += 500L
            }
        }
    }
    delay(1300L)
    println("main:waiting...")
    job.cancelAndJoin() // 取消一个job并且等待它结束
    println("main:exiting...")

//    output:
//    job: I'm sleeping 0 ...
//    job: I'm sleeping 1 ...
//    job: I'm sleeping 2 ...
//    main:waiting...
//    job: I'm sleeping 3 ...
//    job: I'm sleeping 4 ...
//    main:exiting...

}

使计算代码可取消

package cancel

import kotlinx.coroutines.*

/**
 * 协程是可以被取消的
 * 取消的两种方式:
 *  1、定期调用挂起函数来检查取消  job.cancel() // 取消job ====>job.join() // 等待job执行结束
 *  2、显式的检查取消状态  isActive
 */
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:waiting...")
    job.cancelAndJoin() // 取消一个job并且等待它结束
    println("main:exiting...")

//    output:
//    job: I'm sleeping 0 ...
//    job: I'm sleeping 1 ...
//    job: I'm sleeping 2 ...
//    main:waiting...
//    main:exiting...

}

携程在finally中释放资源和执行操作

package cancel

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

/**
 * 协程在被取消时抛出 CancellationException 的可被取消的挂起函数
 * eg:
 * try {……} finally {……} 表达式以及 Kotlin 的 use 函数
 * 一般在协程被取消的时候执行它们的终结动作
 */
fun main() = runBlocking {

    val job = launch {
        try {
            repeat(1000) { i ->
                println("this is i = $i")
                delay(500L)
            }
        }finally {
            println("job finally canceled")
        }

    }
    delay(1300L)
    println("main:waiting...")
    job.cancel() // 取消job
    job.join() // 等待job执行结束
    println("main:exiting...")

//    output:
//    this is i = 0
//    this is i = 1
//    this is i = 2
//    main:waiting...
//    job finally canceled
//    main:exiting...

}

协程在withContext(NonCancellable)执行操作

package cancel

import kotlinx.coroutines.*

/**
 * 需要挂起一个被取消的协程,可以将相应的代码包装在 withContext(NonCancellable) {……} 中,
 * 并使用 withContext 函数以及 NonCancellable 上下文
 */
fun main() = runBlocking {

    val job = launch {
        try {
            repeat(1000) { i ->
                println("this is i = $i")
                delay(500L)
            }
        }finally {
//            println("job finally canceled")
            withContext(NonCancellable){
                println("job: I'm running finally")
                delay(1000L)
                println("job: 我会延迟1s取消,因为我是不可被取消的")
            }
        }

    }
    delay(1300L)
    println("main:waiting...")
    job.cancel() // 取消job
    job.join() // 等待job执行结束
    println("main:exiting...")

//    output:
//    this is i = 0
//    this is i = 1
//    this is i = 2
//    main:waiting...
//    job: I'm running finally
//    job: 我会延迟1s取消,因为我是不可被取消的
//    main:exiting...

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值