文章目录
- 一、结构化并发
- 二、协程作用域构建器 ( runBlocking 函数 | coroutineScope 函数 )
- 二、协程作用域构建器 ( coroutineScope 函数 | supervisorScope 函数 )
- 1、协程作用域构建器概念
- 2、coroutineScope 协程作用域构建器 示例
- 3、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 作用域需要等待 两个子协程执行完毕 , 该作用域才算执行完毕 ;
代码语言:javascript复制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 函数 构建的 协程作用域 , 如果有一个 子协程 执行失败 , 则其它 所有的子协程会被取消 ; 函数原型如下 :
代码语言:javascript复制public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R
supervisorScope 函数 构建的 协程作用域 , 如果有一个 子协程 执行失败 , 其它子协程继续执行 , 不会受到执行失败的子协程影响 ; 函数原型如下 :
代码语言:javascript复制public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R
2、coroutineScope 协程作用域构建器 示例
coroutineScope 函数 构建的 协程作用域 代码示例 : 并发执行两个协程 , 取消其中一个协程 , 另外一个协程也会自动取消 ;
代码语言:javascript复制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 函数 构建的 协程作用域 代码示例 : 并发执行两个协程 , 取消其中一个协程 , 另外一个协程不会受到影响 , 仍然执行完毕 ;
代码语言:javascript复制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" // 返回一个字符串
}
}
}
}
}
执行结果 :