当前位置:嗨网首页>书籍在线阅读

20-非限制与限制协程

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

12.5.2 非限制与限制协程

非限制的协程调度器启动协程时,只能在第一个挂起点被线程调用。能否在线程暂停之后重新启动协程,则完全取决于被调用的挂起函数。非限制协程调度适用于协程不消耗CPU时间片,也不更新任何被特定线程限制的共享数据的场景。

此外,CoroutineScope接口可以在任何协程块中提供上下文属性,它是协程上下文的引用。通过继承父级上下文,特别是runBlocking默认的上下文,可以限制被调用的线程,即将runBlocking默认的上下文限制在主线程上执行。

un main(args: Array<String>) = runBlocking<Unit> {
    val jobs = arrayListOf<Job>()
    jobs += launch(Unconfined) {
        //挂起函数未被调用,协程未开启,工作在主线程上
        println("【Unconfined】: thread ${Thread.currentThread().name}")
        delay(500)
        //挂起协程恢复
        println("【Unconfined】: After delay in thread ${Thread.currentThread(). name}")
    }
    jobs += launch(coroutineContext) {
        // 执行在runBlocking协程所在的主线程上
        println("【coroutineContext】: thread ${Thread.currentThread().name}")
        delay(1000)
        // 执行在runBlocking协程所在的主线程上
        println("【coroutineContext】: thread ${Thread.currentThread().name}")
    }
    jobs.forEach { it.join() }
}

运行上面的代码,输出的结果如下。

【Unconfined】: thread main
【coroutineContext】: thread main
【Unconfined】: After delay in thread kotlinx.coroutines.DefaultExecutor
【coroutineContext】: thread main

父子协程继承了runBlocking{...}的上下文,协程调用delay函数之后,可以继续在主线程中执行;而非限制的协程使用delay函数后,直接在调度线程上恢复。

协程任务作为协程上下文的一部分,可以从coroutineContext[Job]表达式中获取。代码如下。

fun main(args: Array<String>) =runBlocking<Unit> {
    println("My job is ${coroutineContext[Job]}")
}

运行上面的代码,输出的结果如下。

My job is BlockingCoroutine{Active}@3d494fbf