Kotlin====>组合挂起函数

Kotlin组合挂起函数分为默认顺序调用、使用 async 并发、惰性启动的 async、async 风格的函数、使用 async 的结构化并发、取消始终通过协程的层次结构来进行传递

package group

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

/**
 * 使用协程进行并发总是显式的。
 */
suspend fun main() = runBlocking<Unit>{

    println("======> example 1:默认顺序调用")
    // 根据第一个函数调用结果来决定是否调用第二个函数
    // 这些代码都是运行在协程中的,顺序都是默认的
    val one = doSomethingUsefulOne()
    val two = doSomethingUsefulTwo()
    println("The answer is ${one + two}")

    println("======> example 2:使用 async 并发")
    // launch 返回一个 Job 并且不附带任何结果值
    // async 返回一个 Deferred —— 一个轻量级的非阻塞 future
    // Deferred 也是一个 Job,使用 .await() 可以得到一个延期的值,也可以取消它。
    // doSomethingUsefulOne和doSomethingUsefulTwo 没有任何俩,使用async可以尽快得到值
    // 执行速度比example 1 快一倍
    val time = measureTimeMillis {
        val ones = async { doSomethingUsefulOne() }
        val twos = async { doSomethingUsefulTwo() }
        println("The answer is ${ones.await() + twos.await()}")
    }
    println("Completed in $time ms")



    println("======> example 3:惰性启动的 async")
    // async 可以通过将 start 参数设置为 CoroutineStart.LAZY 而变为惰性的。
    // 只有通过 await 获取的时候协程才会启动,或者在 Job 的 start 函数调用的时候。
    // 只是在 println 中调用 await,而没有在单独的协程中调用 start ===> 顺序行为
    // 计算一个值涉及挂起函数时, async(start = CoroutineStart.LAZY) ==替代 ==>标准库中的 lazy 函数。
    val time3 = measureTimeMillis {
        val onel = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
        val twol = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
        // 执行一些计算
        onel.start() // 启动第一个
        twol.start() // 启动第二个
        println("The answer is ${onel.await() + twol.await()}")
    }
    println("Completed in $time3 ms")


    println("======> example 4:async 风格的函数")
    //定义 doSomethingUsefulOne 和 doSomethingUsefulTwo 异步风格的函数
    // 使用 async 协程建造器并带有一个显式的 GlobalScope 引用 ==>GlobalScope.async
    // 这些并不是挂起函数,可以再任何地方使用,异步(并发)执行,并不推荐使用
    // 这里会造成全局捕获异常,但是该程序会继续执行,也就是somethingUsefulOneAsync 仍然在后台执行
    val time5 = measureTimeMillis {
        // 我们可以在协程外面启动异步执行
        val onell = somethingUsefulOneAsync()
        val twoll = somethingUsefulTwoAsync()
        // 但是等待结果必须调用其它的挂起或者阻塞
        // 当我们等待结果的时候,这里我们使用 `runBlocking { …… }` 来阻塞主线程
        runBlocking {
            println("The answer is ${onell.await() + twoll.await()}")
        }
    }
    println("Completed in $time5 ms")

    println("======> example 5:使用 async 的结构化并发")
    //  async 被定义为 CoroutineScope 上的扩展
    //  将携程卸载作用域内,由coroutineScope 函数提供
    // 即使concurrentSum 函数内部发生了错误,它所在作用域中启动的协程都会被取消
    val time6 = measureTimeMillis {
        println("The answer is ${concurrentSum()}")
    }
    println("Completed in $time6 ms")

    println("======> example 6:取消始终通过协程的层次结构来进行传递")
    // 其中一个子协程(即 two)失败,第一个 async 以及等待中的父协程都会被取消:
    try {
        failedConcurrentSum()
    } catch(e: ArithmeticException) {
        println("Computation failed with ArithmeticException")
    }

}

suspend fun doSomethingUsefulOne(): Int {
    delay(1000L) // 假设我们在这里做了一些有用的事
    return 13
}

suspend fun doSomethingUsefulTwo(): Int {
    delay(1000L) // 假设我们在这里也做了一些有用的事
    return 29
}

// somethingUsefulOneAsync 函数的返回值类型是 Deferred<Int>
fun somethingUsefulOneAsync() = GlobalScope.async {
    doSomethingUsefulOne()
}

// somethingUsefulTwoAsync 函数的返回值类型是 Deferred<Int>
fun somethingUsefulTwoAsync() = GlobalScope.async {
    doSomethingUsefulTwo()
}

suspend fun concurrentSum(): Int = coroutineScope {
    val one = async { doSomethingUsefulOne() }
    val two = async { doSomethingUsefulTwo() }
    one.await() + two.await()
}

/**
 * 其中一个子协程(即 two)失败,第一个 async 以及等待中的父协程都会被取消:
 */
suspend fun failedConcurrentSum(): Int = coroutineScope {
    val one = async<Int> {
        try {
            delay(Long.MAX_VALUE) // 模拟一个长时间的运算
            42
        } finally {
            println("First child was cancelled")
        }
    }
    val two = async<Int> {
        println("Second child throws an exception")
        throw ArithmeticException()
    }
    one.await() + two.await()
}

输出如下:

group.GroupMethodKt
======> example 1:默认顺序调用
The answer is 42
======> example 2:使用 async 并发
The answer is 42
Completed in 1039 ms
======> example 3:惰性启动的 async
The answer is 42
Completed in 1005 ms
======> example 4:async 风格的函数
The answer is 42
Completed in 1075 ms
======> example 5:使用 async 的结构化并发
The answer is 42
Completed in 1010 ms
======> example 8:取消始终通过协程的层次结构来进行传递
Second child throws an exception
First child was cancelled
Computation failed with ArithmeticException

参考日志:https://www.kotlincn.net/docs/reference/coroutines/coroutine-context-and-dispatchers.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值