学习协程3:组合挂起函数

这篇具有很好参考价值的文章主要介绍了学习协程3:组合挂起函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Sequential by default

默认是顺序执行。加入有两个挂起函数,他们执行一些计算和远程的服务。如果需要他们顺序执行,先执行doSomethingUsefulOne后执行doSomethingUsefulTwo,然后计算两个的和。

suspend fun doSomethingUsefulOne(): Int {
    delay(1000L) // pretend we are doing something useful here
    return 13
}

suspend fun doSomethingUsefulTwo(): Int {
    delay(1000L) // pretend we are doing something useful here, too
    return 29
}

在实践中,如果我们使用第一个函数的结果来决定是否需要调用第二个函数,或者决定如何调用它,我们就会这样做。我们使用正常的顺序调用,因为协程中的代码与常规代码一样,默认情况下是顺序的。下面的示例通过measureTimeMillis 测量执行两个挂起函数所需的总时间来演示它。

val time = measureTimeMillis {
        val one = doSomethingUsefulOne()
        val two = doSomethingUsefulTwo()
        println("The answer is ${one + two}")
    }
    println("Completed in $time ms")
//output
The answer is 42
Completed in 2023 ms

Concurrent using async

Conceptually, async is just like launch. It starts a separate coroutine which is a light-weight thread that works concurrently with all the other coroutines. The difference is that launch returns a Job and does not carry any resulting value, while async returns a Deferred — a light-weight non-blocking future that represents a promise to provide a result later. You can use .await() on a deferred value to get its eventual result, but Deferred is also a Job, so you can cancel it if needed.

如果在doSomethingUsefulOnedoSomethingUsefulTwo的调用之间没有依赖关系,并且想同步执行来获得答案,使用async。从概念上讲,asynclaunch是一样的,它启动一个单独的协程,与所有其他协程并发工作。不同之处在于,launch返回一个不带任何结果值的job,而async返回一个Defferred,这是一个轻量级的非阻塞的future,并且随后会提供一个结果。您可以对deferred value 使用.await()来获得其最终结果,但deferred也是一个job,因此可以在需要时取消它。

val time = measureTimeMillis {
    val one = async { doSomethingUsefulOne() }
    val two = async { doSomethingUsefulTwo() }
    println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
//output
The answer is 42
Completed in 1025 ms

Lazily started async

Optionally, async can be made lazy by setting its start parameter to CoroutineStart.LAZY. In this mode it only starts the coroutine when its result is required by await, or if its Job’s start function is invoked. Run the following example:
Note that if we just call await in println without first calling start on individual coroutines, this will lead to sequential behavior, since await starts the coroutine execution and waits for its finish, which is not the intended use-case for laziness. The use-case for async(start = CoroutineStart.LAZY) is a replacement for the standard lazy function in cases when computation of the value involves suspending functions.

使用CoroutineStart.LAZY作为启动参数, 只有调用await或者显示的start时才会调用。下面的例子中,如果不加start那么将不是并发的,只有当one.await()执行结束后才会执行two.await()

    val time = measureTimeMillis {
        val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
        val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
        one.start()
        two.start()
        println("The answer is ${one.await() + two.await()}")
    }
    println("Completed in $time ms")
//output
The answer is 42
Completed in 1028 ms

Async-style functions

我们可以定义异步风格的函数来异步调用doSomethingUsefulOnedoSomethingUsefulTwo,使用异步协程构建器GlobalScope引用来选择退出结构化并发。我们用…Async来命名这样的函数。后缀“Async”,以强调它们只启动异步计算,并且需要使用得到的延迟值来获得结果。注意,这些xxxAsync函数不是挂起函数。它们可以在任何地方使用。然而,它们的使用总是意味着用调用代码异步(这里指并发)执行它们的操作。

// The result type of somethingUsefulOneAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulOneAsync() = GlobalScope.async {
	doSomethingUsefulOne()
}

// The result type of somethingUsefulTwoAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulTwoAsync() = GlobalScope.async {
	doSomethingUsefulTwo()
}

val time = measureTimeMillis {
   // we can initiate async actions outside of a coroutine
   val one = somethingUsefulOneAsync()
   val two = somethingUsefulTwoAsync()
   // but waiting for a result must involve either suspending or blocking.
   // here we use `runBlocking { ... }` to block the main thread while waiting for the result
   runBlocking {
       println("The answer is ${one.await() + two.await()}")
   }
}
println("Completed in $time ms")
//output
The answer is 42
Completed in 1033 ms

Structured concurrency with async

Let us take the Concurrent using async example and extract a function that concurrently performs doSomethingUsefulOne and doSomethingUsefulTwo and returns the sum of their results. Because the async coroutine builder is defined as an extension on CoroutineScope, we need to have it in the scope and that is what the coroutineScope function provides:

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


val time = measureTimeMillis {
    println("The answer is ${concurrentSum()}")
}
println("Completed in $time ms")
//output
The answer is 42
Completed in 1026 ms

Cancellation is always propagated through coroutines hierarchy:

只要一个child发生错误,那么兄弟Async和父协程都将被取消文章来源地址https://www.toymoban.com/news/detail-438122.html

fun main() = runBlocking<Unit> {
    try {
        failedConcurrentSum()
    } catch(e: ArithmeticException) {
        println("Computation failed with ArithmeticException")
    }
}

suspend fun failedConcurrentSum(): Int = coroutineScope {
    val one = async<Int> {
        try {
            delay(Long.MAX_VALUE) // Emulates very long computation
            42
        } finally {
            println("First child was cancelled")
        }
    }
    val two = async<Int> {
        println("Second child throws an exception")
        throw ArithmeticException()
    }
    one.await() + two.await()
}
// output
Second child throws an exception
First child was cancelled
Computation failed with ArithmeticException

到了这里,关于学习协程3:组合挂起函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Pytorch深度学习-----神经网络之Sequential的详细使用及实战详解

    PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用(ToTensor,Normalize,Resize ,Compose,RandomCrop) Pytorch深度学习------torchvision中dataset数据集的使用(CIFAR10) Pytorch深度学习--

    2024年02月14日
    浏览(41)
  • 【机器学习】P14 Tensorflow 使用指南 Dense Sequential Tensorflow 实现

    有关 Tensorflow/CUDA/cuDNN 安装,见博客:https://xu-hongduo.blog.csdn.net/article/details/129927665 上图中包含输入层、隐藏层、输出层; 其中输入层为 layer 0 ,输入到网络中的内容为 x ⃗ vec{x} x ; 其中隐藏层有三层, layer 1 , layer 2 , layer 3 ; 其中输出层为 layer 4 ,输出内容为 a ⃗ [

    2023年04月09日
    浏览(39)
  • 【学习FreeRTOS】第5章——FreeRTOS任务挂起与恢复

    vTaskSuspend() ——挂起任务(类似暂停,可恢复,但删除任务,无法恢复) vTaskResume() ——恢复被挂起的任务 xTaskResumeFromISR()—— 在中断中恢复被挂起的任务 形参:待挂起任务句柄 此函数用于挂起任务,使用时需将宏 INCLUDE_vTaskSuspend 配置为 1。 无论优先级如何,被挂起的任务

    2024年02月13日
    浏览(39)
  • Pytorch学习:神经网络模块torch.nn.Module和torch.nn.Sequential

    官方文档:torch.nn.Module CLASS torch.nn.Module(*args, **kwargs) 所有神经网络模块的基类。 您的模型也应该对此类进行子类化。 模块还可以包含其他模块,允许将它们嵌套在树结构中。您可以将子模块分配为常规属性: training(bool) -布尔值表示此模块是处于训练模式还是评估模式。

    2024年02月10日
    浏览(42)
  • 浅谈Lua协程和函数的尾调用

    虽然不经常用到协程,但是也不能谈虎色变。同时,在有些场景,协程会起到一种不可比拟的作用。所以,了解它,对于一些功能,也会有独特的思路和想法。 概念 关于进程和线程的概念就不多说。 那么从多线程的角度来看,协程和线程有点类似:拥有自己的栈,局部变量

    2024年02月10日
    浏览(43)
  • verilog 学习笔记 —— 时序逻辑 Sequential Logics (Latches and Flip-Flops 锁存器和触发器)

    1. D flip-flop D触发器 2. D flip-flop  D触发器 3. DFF with reset  带复位的D触发器  4. 带复位值的D触发器 5. DFF with asynchronous reset 带异步复位功能的 D触发器 6. DFF with byte enable   带位启动的触发器 7. D Latch  D锁存器 8. DFF  9. DFF   10. DFF+gate   11. Mux and DFF   12. DFFs and gates   13

    2024年02月04日
    浏览(58)
  • Excel·VBA二维数组组合函数、组合求和

    之前的文章《Excel·VBA数组组合函数、组合求和》和《Excel·VBA数组排列函数》,都是针对 一维数组 的组合和排列 二维数组组合:对一个 m行*n列 的二维数组,每行抽取1个元素进行组合,则共有 n ^ m 个组合 代码思路,类似之前的文章“VBA排列函数”尾数循环的方式 举例 组合

    2024年02月11日
    浏览(49)
  • 【unity细节】Default constructor not found for type Player(找不到默认构造函数)

    👨‍💻个人主页 :@元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏 :unity细节和bug : Default constructor not found for type Player System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic, System.Boolean wrapExceptions) (at 88e4733ac7bc4ae1b496735e6b83bbd3:0) System.Runt

    2024年02月10日
    浏览(41)
  • 【Linux】进程的状态(运行、阻塞、挂起)详解,揭开孤儿进程和僵尸进程的面纱,一篇文章万字讲透!!!!进程的学习②

    目录 1.进程排队 时间片 时间片的分配 结构体内存对齐 偏移量补充 对齐规则  为什么会有对齐 2.操作系统学科层面对进程状态的理解 2.1进程的状态理解 ①我们说所谓的状态就是一个整型变量,是task_struct中的一个整型变量 ②.状态决定了接下来的动作 2.2运行状态 2.3 阻塞状

    2024年04月14日
    浏览(44)
  • Python学习之路-多任务:协程

    协程,又称微线程,纤程。英文名Coroutine。协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这

    2024年01月17日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包