协程和协程作用域
理清子协程,父协程,协程作用域,协程生命周期,协程作用域的生命周期等的关系。
1、协程是在协程作用域内执行的轻量级并发单元。当协程的代码块执行完成时,它会挂起并返回到其父协程或顶层协程中。
2、父协程通过调用协程构建器(如 launch
、async
)来启动子协程。在启动子协程时,子协程会继承父协程的上下文(包括调度器、异常处理器等)。这意味着子协程会以与父协程相同的上下文执行。父协程可以通过 join()
方法等待子协程执行完成,以确保子协程的结果可用。
父协程可以通过取消操作来取消子协程。当父协程被取消时,它会递归地取消所有的子协程。子协程会接收到取消事件,并根据取消策略来决定如何处理取消。
父协程和子协程之间的关系可以帮助管理协程的层次结构和生命周期。通过父协程启动和取消子协程,可以有效地组织和控制协程的执行流程,实现更灵活和可靠的协程编程。
fun main() {
runBlocking {
val parentJob = launch {
val childJob = launch {
printMsg("childJob start")
delay(500)
printMsg("childJob complete")
}
childJob.join()
printMsg("parentJob complete")
}
parentJob.join()
parentJob.cancel()
printMsg("parentJob cancel")
}
}
//日志
main @coroutine#3 childJob start
main @coroutine#3 childJob complete
main @coroutine#2 parentJob complete
main @coroutine#1 parentJob cancel
Process finished with exit code 0
fun main() {
runBlocking {
val parentJob = launch {
val childJob = launch {
printMsg("childJob start")
delay(500)
printMsg("childJob complete")
}
childJob.join()
printMsg("parentJob complete")
}
//parentJob.join() <----------变化在这里
parentJob.cancel()
printMsg("parentJob cancel")
}
}
//日志
main @coroutine#1 parentJob cancel
Process finished with exit code 0
3、协程作用域(CoroutineScope
)是用于协程的上下文环境,它提供了协程的启动和取消操作的上下文。协程作用域定义了协程的生命周期,并决定了协程在何时启动、在何时取消。
协程作用域是一个接口,定义了两个主要方法:
launch
:用于启动一个新的协程。launch
方法会创建一个新的协程,并将其添加到当前协程作用域中。启动的协程将继承父协程的上下文,并在协程作用域内执行。cancel
:用于取消协程作用域中的所有协程。cancel
方法会发送一个取消事件到协程作用域中的所有协程,使它们退出执行。
协程作用域与协程之间的关系是协程在协程作用域内执行的。协程作用域为协程提供了上下文环境,使得协程可以访问到必要的上下文信息,例如调度器(Dispatcher
)和异常处理器(ExceptionHandler
)。通过在协程作用域中启动协程,可以确保协程的生命周期受到协程作用域的管理,并且在协程作用域取消时,所有协程都会被取消。
fun main() = runBlocking {
coroutineScope {
launch {
delay(1000)
printMsg("Coroutine 1 completed")
}
launch(Job()) { <---------协程2不使用协程作用域的上下文,会脱离协程作用域的控制
delay(2000)
printMsg("Coroutine 2 completed")
}
}
printMsg("Coroutine scope completed")
}
//日志
main @coroutine#2 Coroutine 1 completed 1685615335423
main @coroutine#1 Coroutine scope completed 1685615335424 <-------协程1执行完,协程作用域就执行完
Process finished with exit code 0 <---------程序退出
4、如果使用 GlobalScope.launch
创建协程,则协程会成为全局协程,它的生命周期独立于程序的其他部分。当协程的代码执行完毕后,全局协程不会自动退出,除非应用程序本身退出。因此,全局协程可以在整个应用程序的生命周期内持续执行,直到应用程序终止。
如果使用协程作用域(例如 runBlocking
、coroutineScope
等)创建协程,则协程的生命周期受协程作用域的限制。当协程的代码执行完毕后,它会返回到作用域的父协程或顶级协程中,而不会自动退出。
5、当协程作用域内的所有协程执行完成后,协程作用域仍然存在,但其中的协程会被标记为完成状态。这意味着协程作用域仍然可以用于启动新的协程,但之前的协程不会再执行。
协程作用域的生命周期不仅仅依赖于其中的协程执行状态,还取决于其父协程或顶级协程的生命周期。如果协程作用域的父协程或顶级协程被取消或完成,那么协程作用域也将被取消。
fun main() = runBlocking {
coroutineScope {
launch {
delay(1000)
printMsg("Coroutine 1 completed")
}
launch {
delay(2000)
printMsg("Coroutine 2 completed")
}
}
printMsg("Coroutine scope completed")
}
//日志
main @coroutine#2 Coroutine 1 completed
main @coroutine#3 Coroutine 2 completed
main @coroutine#1 Coroutine scope completed
Process finished with exit code 0 <---------程序退出
链接:https://juejin.cn/post/7239620589790822457
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。