fun main() {
GlobalScope.launch { // 在后台启动一个新的协程并继续
delay(1000L)
println("World!")
}
println("Hello,") // 主线程中的代码会立即执行
runBlocking { // 但是这个表达式阻塞了主线程
delay(2000L) // ……我们延迟 2 秒来保证 JVM 的存活
}
}
这里因为 delay 是一个特殊的 挂起函数 ,
它不会造成挂起线程,但是会 挂起 协程,并且只能在协程中使用。
普通终止
val job = GlobalScope.launch { // 启动一个新协程并保持对这个作业的引用
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // 等待直到子协程执行结束
作用域启动
fun main() = runBlocking { // this: CoroutineScope
launch { // 在 runBlocking 作用域中启动一个新协程
delay(1000L)
println("World!")
}
println("Hello,")
}
coroutineScope 声明作用域
fun main() = runBlocking { // this: CoroutineScope
launch {
delay(200L)
println("Task from runBlocking")
}
coroutineScope { // 创建一个协程作用域
launch {
delay(500L)
println("Task from nested launch")
}
delay(100L)
println("Task from coroutine scope") // 这一行会在内嵌 launch 之前输出
}
println("Coroutine scope is over") // 这一行在内嵌 launch 执行完毕后才输出
}
提取函数
fun main() = runBlocking {
launch { doWorld() }
println("Hello,")
}
// 这是你的第一个挂起函数
suspend fun doWorld() {
delay(1000L)
println("World!")
}
取消与超时
val job = launch {
repeat(1000) { i ->
println("job: I'm sleeping $i ...")
delay(500L)
}
}
delay(1300L) // 延迟一段时间
println("main: I'm tired of waiting!")
job.cancel() // 取消该任务
job.join() // 等待任务执行结束
println("main: Now I can quit.")
// 协程的取消是 协作 的。一段协程代码必须协作才能被取消。
// 它们检查协程的取消, 并在取消时抛出 CancellationException
// 然而,如果协程正在执行计算任务,并且没有检查取消的话,那么它是不能被取消的
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (i < 5) { // 一个执行计算的循环,只是为了占用 CPU
// while (isActive) { // 替换成这个就可以取消了
// 每秒打印消息两次
if (System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
delay(1300L) // 等待一段时间
println("main: I'm tired of waiting!")
job.cancelAndJoin() // 取消一个任务并且等待它结束
println("main: Now I can quit.")
// 一般情况下挂起会抛出 CancellationException,通常在finally 中是非阻塞的,并不会调起任何挂起函数。
// 然而,好多时候,需要挂起一个被取消的协程,此时就需要将代码包装在 withContext(NonCancellable){...}
val job = launch {
try {
repeat(1000) { i ->
println("job: I'm sleeping $i ...")
delay(500L)
}
} finally {
withContext(NonCancellable) {
println("job: I'm running finally")
delay(1000L)
println("job: And I've just delayed for 1 sec because I'm non-cancellable")
}
}
}
delay(1300L) // 延迟一段时间
println("main: I'm tired of waiting!")
job.cancelAndJoin() // 取消该任务并等待它结束
println("main: Now I can quit.")
// 如果你需要做一些各类使用超时的特别的额外操作,可以使用类似 [withTimeout] 的 [withTimeoutOrNull]函数,
// 并把这些会超时的代码包装在 `try {...} catch (e: TimeoutCancellationException) {...}` 代码块中,
// 而 [withTimeoutOrNull] 通过返回 `null` 来进行超时操作,从而替代抛出一个异常
val result = withTimeoutOrNull(1300L) {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
"Done" // 在它运行得到结果之前取消它
}
println("Result is $result")
网友评论