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