
在
博客中介绍了 结构化并发 ;
结构化并发的作用 : 协程任务 运行时 , 必须指定其 CoroutineScope 协程作用域 , 其会 追踪所有的 协程任务 , CoroutineScope 协程作用域 可以 取消 所有由其启动的协程任务 ;
结构化并发 使用场景 :
结构化并发 通过 协程作用域 CoroutineScope 管理协程任务 ;
协程作用域 构建器 是 结构化并发 的重要组成部分 ;
常用的 协程作用域构建器 有 coroutineScope 和 runBlocking ;
public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T 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 函数 构建的 协程作用域 , 如果有一个 子协程 执行失败 , 则其它 所有的子协程会被取消 ; 函数原型如下 :
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): RsupervisorScope 函数 构建的 协程作用域 , 如果有一个 子协程 执行失败 , 其它子协程继续执行 , 不会受到执行失败的子协程影响 ; 函数原型如下 :
public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R 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 协程也被取消 ;

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" // 返回一个字符串
}
}
}
}
}执行结果 :
