【Kotlin 协程】协程启动 ⑤ ( 协程作用域构建器 | runBlocking 函数 | coroutineScope 函数 | supervisorScope 函数 )
文章目录
一、结构化并发
在
- 【Kotlin 协程】协程底层实现 ② ( 协程调度器 | 协程任务泄漏 | 结构化并发 )
- 【Kotlin 协程】协程底层实现 ③ ( 结构化并发 | MainScope 作用域 | 取消协程作用域 | Activity 实现 CoroutineScope 协程作用域接口 )
- 【Kotlin 协程】协程底层实现 ④ ( 结构化并发 | viewModelScope 作用域示例 )
博客中介绍了 结构化并发 ;
结构化并发的作用 : 协程任务 运行时 , 必须指定其 CoroutineScope 协程作用域 , 其会 追踪所有的 协程任务 , CoroutineScope 协程作用域 可以 取消 所有由其启动的协程任务 ;
结构化并发 使用场景 :
- 协程任务取消 : 在不需要协程任务的时候 , 取消协程任务 ;
- 追踪协程任务 : 追踪正在执行的协程任务 ;
- 发出错误信号 : 如果 协程任务执行失败 , 发出错误信号 , 表明执行任务出错 ;
二、协程作用域构建器 ( runBlocking 函数 | coroutineScope 函数 )
结构化并发 通过 协程作用域 CoroutineScope 管理协程任务 ;
协程作用域 构建器 是 结构化并发 的重要组成部分 ;
常用的 协程作用域构建器 有 coroutineScope 和 runBlocking ;
- runBlocking 是 普通函数 , 可以在 普通的代码位置使用 , 将 主线程 或 子线程 包装成 协程体 , 在该协程中执行 协程任务 , 会 阻塞当前的线程 ; 函数原型如下 :
public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T
- coroutineScope 是 挂起函数 , 只能在 协程体 中使用 , 该协程会在另外的独立的线程执行 协程任务 , 不会干扰当前启动协程的线程 ; 函数原型如下 :
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R
共同点 : 这两个 协程作用域构建器 构建的协程 都会等待 协程体 中的所有 协程任务 和 子协程 执行完毕 ;
代码示例 : 在下面的代码中 ,
runBlocking 可以在普通的函数中执行 , 将主线程包装成了协程体 ;
但是 coroutineScope 函数 由于是 挂起函数 , 只能在 协程体 中使用 ;
该 coroutineScope 协程作用域 将 子协程 job0 和 job1 包裹起来 ,
coroutineScope 作用域需要等待 两个子协程执行完毕 , 该作用域才算执行完毕 ;
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity(){
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking {
// 调用 runBlocking 函数 , 可以将 主线程 包装成 协程
coroutineScope {
// 该 coroutineScope 协程作用域 将 子协程 job0 和 job1 包裹起来
// coroutineScope 作用域需要等待 两个子协程执行完毕 , 该作用域才算执行完毕
val job0 = launch {
delay(2000)
Log.i(TAG, "job0 协程执行完毕")
}
val job1 = async {
delay(2000)
Log.i(TAG, "job1 协程执行完毕")
"Hello" // 返回一个字符串
}
}
}
}
}
二、协程作用域构建器 ( coroutineScope 函数 | supervisorScope 函数 )
1、协程作用域构建器概念
coroutineScope 函数 构建的 协程作用域 , 如果有一个 子协程 执行失败 , 则其它 所有的子协程会被取消 ; 函数原型如下 :
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R
supervisorScope 函数 构建的 协程作用域 , 如果有一个 子协程 执行失败 , 其它子协程继续执行 , 不会受到执行失败的子协程影响 ; 函数原型如下 :
public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R
2、coroutineScope 协程作用域构建器 示例
coroutineScope 函数 构建的 协程作用域 代码示例 : 并发执行两个协程 , 取消其中一个协程 , 另外一个协程也会自动取消 ;
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity(){
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking {
// 调用 runBlocking 函数 , 可以将 主线程 包装成 协程
coroutineScope {
// 该 coroutineScope 协程作用域 将 子协程 job0 和 job1 包裹起来
// coroutineScope 作用域需要等待 两个子协程执行完毕 , 该作用域才算执行完毕
// coroutineScope 函数 构建的 协程作用域 ,
// 如果有一个 子协程 执行失败 , 则其它 所有的子协程会被取消 ;
val job0 = launch {
Log.i(TAG, "job0 协程开始执行")
delay(2000)
Log.i(TAG, "job0 协程执行完毕")
}
val job1 = async {
Log.i(TAG, "job1 协程开始执行")
delay(1000)
// 抛出异常 , job1 执行取消
Log.i(TAG, "job1 协程 抛出异常取消执行")
throw java.lang.IllegalArgumentException()
Log.i(TAG, "job1 协程执行完毕")
"Hello" // 返回一个字符串
}
}
}
}
}
执行结果 : 在 job1 协程抛出异常后 , 未执行完毕的 job0 协程也被取消 ;
3、supervisorScope 协程作用域构建器 示例
supervisorScope 函数 构建的 协程作用域 代码示例 : 并发执行两个协程 , 取消其中一个协程 , 另外一个协程不会受到影响 , 仍然执行完毕 ;
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity(){
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking {
// 调用 runBlocking 函数 , 可以将 主线程 包装成 协程
supervisorScope {
// supervisorScope 函数 构建的 协程作用域 ,
// 如果有一个 子协程 执行失败 ,
// 其它子协程继续执行 , 不会受到执行失败的子协程影响 ;
val job0 = launch {
Log.i(TAG, "job0 协程开始执行")
delay(2000)
Log.i(TAG, "job0 协程执行完毕")
}
val job1 = async {
Log.i(TAG, "job1 协程开始执行")
delay(1000)
// 抛出异常 , job1 执行取消
Log.i(TAG, "job1 协程 抛出异常取消执行")
throw java.lang.IllegalArgumentException()
Log.i(TAG, "job1 协程执行完毕")
"Hello" // 返回一个字符串
}
}
}
}
}
执行结果 :
相关文章
- [Kotlin] When to add () and when not to
- Kotlin 朱涛-1 基础语法 变量 类型 函数 流程控制
- Kotlin 朱涛-15 协程 挂起函数 suspend CPS Continuation
- [Kotlin] Method expressions
- [Kotlin] I/O readline
- Android修行手册之Kotlin-【变量和常量】、【基础类型】、【字符串】、【类型转换】、【函数定义】、【匿名函数】和【可变参数】
- 熬夜再战Android之修炼Kotlin-互操作篇
- 熬夜再战Android之修炼Kotlin-为什么要搞她?
- Android kotlin 系列讲解(进阶篇)Jetpack系列之LiveData
- Android kotlin 系列讲解(基础篇) 带返回值函数的小技巧
- Android kotlin 系列讲解(基础篇) 高级语法let函数、apply函数、also函数、run函数和with函数
- Kotlin 扩展函数与属性 实例代码
- 《Kotin 极简教程》第12章 使用 Kotlin 集成Gradle 开发
- 《Kotlin 程序设计》第六章 Kotlin 函数式编程(FP)
- Kotlin 函数式编程 + 递归 : 构建 "树" 数据结构通用模型
- Kotlin 函数式编程思想 FP in Kotlin
- 【Kotlin 协程】协程的挂起和恢复 ① ( 协程的挂起和恢复概念 | 协程的 suspend 挂起函数 )
- 【Kotlin 协程】协程取消 ② ( CPU 密集型协程任务取消 | 使用 isActive 判定协程状态 | 使用 ensureActive 函数取消协程 | 使用 yield 函数取消协程 )
- Kotlin — 适用于数据科学
- Android kotlin AnyLayer(github官网)框架弹窗(+RecyclerView(androidx+BRVAH3.0.6))
- Android kotlin 实现可点击可滑动顶部导航栏(AppBarLayout+TabLayout)和左右切换可滑动页面(ViewPager)的功能
- android kotlin基础-- 变量 函数 数据类型