美文网首页
Kotlin 协程之基础

Kotlin 协程之基础

作者: 莫库施勒 | 来源:发表于2019-05-23 16:34 被阅读0次
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")

相关文章

网友评论

      本文标题:Kotlin 协程之基础

      本文链接:https://www.haomeiwen.com/subject/tprbzqtx.html