启动模式
模式 | 描述 |
---|---|
缺省 | 默认为DEFAULT |
DEFAULT | 立即等待被调度执行() |
ATOMIC | 立即等待被调度执行,并且开始执行前无法被取消,直到执行完毕或者遇到第一个挂起点suspend |
UNDISPATCHED | 立即在当前线程执行协程体内容 |
LAZY | 需要手动触发才会进入等待调度 |
示例
缺省
协程采用缺省的启动器, 当父协程执行完1,3后就会调度子协程执行2
/**
* 启动模式, 缺省时
*
* 协程立即等待被调度执行(等待被调度,不是立即执行)
*
* 打印:
* 1
* 3
* 2
*/
@Test
fun coroutineStart() = runBlocking {
println("1")
launch {
println("2")
}
println("3")
delay(3000)
}
DEFAULT
/**
* DEFAULT启动模式,效果同缺省时一致
*/
@Test
fun default() = runBlocking {
println("1")
launch( start = CoroutineStart.DEFAULT) {
println("2")
}
println("3")
delay(3000)
}
UNDISPATCHED
UNDISPATCHED的协程会立即执行,所以1后先执行2完毕后才能执行到3
/**
* UNDISPATCHED启动模式,立即运行该协程体内容(相比其它启动方式少了等待过程)
*
* 打印:
* 1
* 2
* 3
*/
@Test
fun unDispatched() = runBlocking {
println("1")
launch(start = CoroutineStart.UNDISPATCHED) {
//2优先于3执行
println("2")
}
println("3")
}
LAZY
lazy如字面意思,懒惰,需要我们主动触发才能进入等待调度阶段,否则不会有机会执行到。
- 调用 Job.start,主动触发协程的调度执行
- 调用 Job.join,隐式的触发协程的调度执行
/**
* lazy启动方式,需要主动触发才能进入等待调度阶段
*
* - 调用 Job.start,主动触发协程的调度执行
* - 调用 Job.join,隐式的触发协程的调度执行
*
* 使用start触发打印出:
* 1
* 3
* 2
* 使用join触发打印出:
* 1
* 2
* 3
* 如果下述例子去掉job.start(),则肯定是:
* 1
* 3
*/
@Test
fun lazy() = runBlocking {
println("1")
val job = launch(start = CoroutineStart.LAZY) {
//2优先于3执行
println("2")
}
//lazy需要手动触发,让其协程进入等待调度阶段
job.start()
//join会堵塞当前协程等待job协程执行完毕
//job.join()
println("3")
}
/**
* 注意一旦lazy协程体没有通过start执行完毕或者通过cancel取消掉,则runBlocking永远不会退出。
* runBlocking会等到里面全部协程结束才退出
*
* 打印出:
* 1
* 3
* 4
*/
@Test
fun lazy2() = runBlocking {
println("1")
val job = launch(start = CoroutineStart.LAZY) {
println("2")
}
println("3")
//job.start()
//job.cancel()
delay(3000)
println("4")
}
ATOMIC
ATOMIC启动模式,与DEFAULT类似,立即等待被调度执行
区别在于: ATOMIC开始执行前无法被取消,直到执行完毕或者遇到第一个挂起点, DEFAULT执行前可以被取消。
/**
* ATOMIC启动模式,立即等待被调度执行,并且开始执行前无法被取消,直到执行完毕或者遇到第一个挂起点。
*
* 该示例可以看出在同样经过cancel操作后,atomic协程依旧会被启动,而其它则不会启动了
* 打印出:
* 1
* 3
* atomic run
*/
@Test
fun atomic() = runBlocking {
println("1")
val job = launch(start = CoroutineStart.ATOMIC) {
println("atomic run")
}
job.cancel()
println("3")
}
/**
*
* 该示例演示atomic被cancel后遇到第一个挂起点取消运行的效果
*
* 打印出:
*
* 1
* 2
* atomic run
* 3
*/
@Test
fun atomic2() = runBlocking {
println("1")
val job = launch(start = CoroutineStart.ATOMIC) {
println("atomic run")
//遇到了挂起点,cancel生效,不会再执行打印atomic end
delay(3000)
println("atomic end")
}
job.cancel()
println("2")
delay(5000)
println("3")
}
/**
* 该例子可以看出,在未运行前,default,lazy可以被cancel取消,
* unDidpatcher因为会立即在当前线程执行,所以该例子中的cancel本身没啥意义了
*
* 输出:
* 1
* unDispatcherJob run
* 2
* atomic run
*/
@Test
fun atomic3() = runBlocking {
println("1")
val job = launch(start = CoroutineStart.ATOMIC) {
println("atomic run")
}
job.cancel()
val defaultJob = launch(start = CoroutineStart.DEFAULT) {
println("default run")
}
defaultJob.cancel()
val lazyJob = launch(start = CoroutineStart.LAZY) {
println("lazyJob run")
}
lazyJob.start()
lazyJob.cancel()
val unDispatcherJob = launch(start = CoroutineStart.UNDISPATCHED) {
println("unDispatcherJob run")
}
unDispatcherJob.cancel()
println("2")
}