多个挂起函数
同一协程下多个挂起函数,顺序执行.如下所示,test1()和test2()顺序执行,得到结果,并最终打印.
fun main() = runBlocking {
var time = measureTimeMillis {
val one = test1()
val two = test2()
val result = one + two
println("result is $result")
}
println("end $time")
}
suspend fun test1():Int{
delay(500)
return 10
}
suspend fun test2():Int{
delay(500)
return 20
}
//输出
result is 30
end time cost 1016
异步执行多个挂起函数 async/await
- 通过async可以并发启动两个协程
- await等待协程结果
fun main() = runBlocking {
var time = measureTimeMillis {
val one = async {test1()}
val two = async {test2()}
val result = one.await() + two.await()
println("result is $result")
}
println("end time cost $time")
}
suspend fun test1():Int{
delay(500)
return 10
}
suspend fun test2():Int{
delay(500)
return 20
}
//输出
result is 30
end time cost 521
async与launch
- async和launch都返回一个job ,区别在于是否携带结果.
- async返回了一个Deferred延期任务,能够通过await获得结果.Deferred也继承自job
- launch返回一个job,不带结果
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T> {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyDeferredCoroutine(newContext, block) else
DeferredCoroutine<T>(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
获取作业job
async {
println("${Thread.currentThread().name} test a")
println("${coroutineContext[Job]}")
coroutineContext[Job]?.cancelAndJoin()
}
async 惰性任务 CoroutineStart.LAZY
- 有时候定义好异步任务,不需要马上启动,这时候需要用惰性启动来定义任务.在满足条件的时候启动.
- 如果不调用start,在await的时候,也会启动任务.但是会顺序执行.
fun main() = runBlocking {
var time = measureTimeMillis {
val one = async(start = CoroutineStart.LAZY) {test1()}
val two = async(start = CoroutineStart.LAZY) {test2()}
one.start()
two.start()
val result = one.await() + two.await()
println("result is $result")
}
println("end time cost $time")
}
同一作用域下多个异步任务
当有一个异步任务失败时,会造成同一作用域下其它任务失败.
fun main() = runBlocking {
var time = measureTimeMillis {
val one = async(start = CoroutineStart.LAZY) {test1()}
val two = async(start = CoroutineStart.LAZY) {test2()}
one.start()
two.start()
val result = one.await() + two.await()
println("result is $result")
}
println("end time cost $time")
}
suspend fun test1():Int{
try {
delay(Long.MAX_VALUE)
}finally {
println("test1 cancelled")
}
return 10
}
suspend fun test2():Int{
delay(500)
throw IllegalStateException("test2 exception")
return 20
}
协程上下文与调度器
协程总是运行在协程上下文中,它是一些列元素的集合
- 协程调度器 CoroutineDispatcher, 它确定协程运行在哪类线程上. MainCoroutineDispatcher/CoroutineDispatcher
- 当没有指定上下文时,它默认从父协程中继承.
fun main() = runBlocking {
launch(context = Dispatchers.Default){
println("test default ${Thread.currentThread().name}")
}
launch {
println("test Main ${Thread.currentThread().name}")
}
launch(context = Dispatchers.IO){
println("test IO ${Thread.currentThread().name}")
}
//
launch(context = Dispatchers.Unconfined){
println("test Unconfined ${Thread.currentThread().name}")
}
coroutineScope {
println("test coroutineScope ${Thread.currentThread().name}")
20
}
println("end of main")
}
//输出
test default DefaultDispatcher-worker-1
test IO DefaultDispatcher-worker-1
test Unconfined main
test coroutineScope main
end of main
test Main main
协程调试
调试参数
-Dkotlinx.coroutines.debug
var a = async {
println("${Thread.currentThread().name} test a")
}
a.start()
协程命名
可以支持组合多个context的属性, + 是在CoroutineContext中重载的运算符
fun main() = runBlocking {
val v1 = async(Dispatchers.Default + CoroutineName("test")) {
delay(400)
println("coroutine ${Thread.currentThread().name}")
}
}
父协程与子协程协同
父协程取消
当父协程取消时,会自动取消所有的子协程.子协程与父协程具有相同的scope.
fun main() = runBlocking {
val req = launch {
GlobalScope.launch {
delay(100)
println("start in global scope")
delay(1000)
println("end in global scope")
}
launch {
delay(100)
println("start in coroutine scope")
delay(1000)
println("will be canceled if parent canceled")
}
}
delay(500)
req.cancel()
delay(1000)
println("end of all")
}
//输出
start in coroutine scope
start in global scope
end in global scope
end of all
父协程等待
父协程总是等待所有子协程结束,才会结束自身.
fun main() = runBlocking {
//如果把子协程放到这个作用域下,则all done 不会先执行
// coroutineScope{
//
// }
val req = launch {
repeat(3){
delay((it + 1) * 300L)
println("coroutine $it is done")
}
println("done !!!!!")
}
println("all done !!!!!")
}
协程与activity生命周期同步
在app中添加依赖
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1-native-mt"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1-native-mt"
构建全局的scope
private val mainScope = MainScope()
同步生命周期
override fun onDestroy() {
super.onDestroy()
mainScope.cancel()
}