协程启动
launch与async构建器都用来启动新的协程
- launch 返回一个Job并不附带任何结果值
- async 返回一个Deferred,Deferred也是一个Job,可以使用await()在一个延期的值上得到它最终结果
fun testCoroutineBuilder() = runBlocking {
val job1 = launch {
delay(200)
println("job1 finished")
}
val job2 = async {
delay(200)
println("job2 finished")
"job2 result"
}
println(job2.await())
}
等待一个作业
- join与await
- 组合并发
fun testAsync() = runBlocking {
val time = measureTimeMillis {
val doOne = async { doOneAsync() }
val doTwo = async { doTwoAsync() }
println("The result : ${doOne.await() + doTwo.await()}")
}
println("Completed in $time ms")
}
suspend fun doOneAsync(): Int {
delay(200)
return 13
}
suspend fun doTwoAsync(): Int {
delay(500)
return 14
}
协程的启动模式
- DEFAULT: 协程创建后,立即开始调度,在调度前如果协程被取消,其将直接进入取消相应状态
- ATOMIC: 协程创建后,立即开始调度,协程执行到第一个挂起点之前(例如 delay)不响应取消
- LAZY:只有协程被需要时,包括主动调用协程的start,join或者await等函数时才会开始调度,如果调度前就被取消,那么该协程将直接进入异常状态
- UNDISPATHERD:协程创建立即在当前函数调用栈中执行,直到遇到第一个真正挂起的点
// 使用Dispatchers.IO 该协程仍在在主线程
async(context = Dispatchers.IO,start = CoroutineStart.UNDISPATCHED){
println("thread : ${Thread.currentThread().name}")
}
结构化并发
- 取消任务,当某项任务不在需要时取消它
- 追踪任务,当任务执行,追踪它
- 发出错误信号,当协程失败时,发出错误信号表明有错误发生
协程的作用域构建器
coroutineScope与runBlocking
- runBlocking是常规函数,而coroutineScope是挂起函数
- 他们都会等待协程体以及所有子协程结束,主要区别于runBlocking方法会阻塞当前线程来等待,而coroutineScope只是挂起,会释放底层线程永不其他用途
- coroutineScope:一个协程失败了,所有其他兄弟协程也会被取消
- supervisorScope: 一个协程挂了,不会影响其他兄弟协程
coroutineScope 实例
fun textCoroutineScopeBuilder() = runBlocking {
coroutineScope {
launch {
delay(400)
println("job1 finished")
}
launch {
delay(200)
println("job2 finished")
throw IllegalArgumentException()
}
}
}
结果
job2 finished
···异常日志
Process finished with exit code 1
supervisorScope 实例
fun textCoroutineScopeBuilder() = runBlocking {
supervisorScope {
launch {
delay(400)
println("job1 finished")
}
launch {
delay(200)
println("job2 finished")
throw IllegalArgumentException()
}
}
}
结果
job2 finished
···异常日志
job1 finished
Process finished with exit code 0
Job对象的生命周期
Job对象
- 对于每一个创建的协程(通过launch或者async),会返回一个Job实例,该实例是协程的唯一标识,并且负责管理协程的生命周期
- 一个任务可以包含一系列状态:新创建(New)、活跃(Active)、完成中(Completing)、已完成(Completed)、取消中(Cancelling)和已取消(Cancelled)虽然我们无法直接访问这些状态,但是我们可以访问Job的属性:isActive、isCancelled和isCompleted
- 如果协程处于活跃状态,协程运行出错或者调用Job.cancel()都会将当前任务置为取消中(Cancelling)状态(isActive=false,isCancelled=true)。当所有子协程都完成后,协程会进入已取消(Cancelled)状态,此时isCompleted = true