【问题标题】:How to run two jobs in parallel but wait for another job to finish using kotlin coroutines如何使用 kotlin 协程并行运行两个作业但等待另一个作业完成
【发布时间】:2019-05-24 02:11:45
【问题描述】:

我在下面有这些工作:

  1. 异步扩充复杂的日历视图
  2. 下载事件A
  3. 下载事件 B
  4. 向其父级添加日历视图
  5. 在日历中添加 A 事件
  6. 将 B 事件添加到日历中

我想要

  • 1、2、3要异步启动,
  • 4 必须等待 1
  • 5 必须等待 2 和 4
  • 6 必须等待 3 和 4
  • 6 和 5 不应该相互依赖,可以在不同的时间运行。
  • 4 只依赖于 1,所以它可以在 2 或 3 完成之前运行。

我尝试过异步等待,但它使它们同时完成(如预期的那样)。我认为这个例子可能是学习并行编程概念的好方法,比如信号量互斥锁或自旋锁。但这对我来说太复杂了。

我应该如何使用 Kotlin 协程来实现这些?

【问题讨论】:

    标签: kotlin parallel-processing coroutine


    【解决方案1】:

    这很简单。您需要做的就是:

    1. 实现CoroutineScope并创建CoroutineContext,或使用GlobalScope
    2. 使用本地CoroutineScopeGlobalScope.launch() 启动协程。
    3. 在协程中使用async/await 来运行/等待异步操作。

    您可以将下一个代码应用于您的算法(所有解释都在 cmets 中):

    class SomeClass : CoroutineScope {
        private var job: Job = Job()
    
        // creating local CoroutineContext
        override val coroutineContext: CoroutineContext
            get() = Dispatchers.Main + job
    
        // cancel the Job if it is no longer needed
        fun onClear() {
            job.cancel()
        }
    
        fun doJob() {
            // launch coroutine
            launch {
                // run Job1, Job2, Job3 in parallel, asyncIO - is an extension function on CoroutineScope
                val d1 = asyncIO { job1() }
                val d2 = asyncIO { job2() }
                val d3 = asyncIO { job3() }
    
                // waiting for result of Job1
                val job1Result = d1.await()
    
                // run Job4
                val d4 = asyncIO { job4(job1Result) }
    
                // waiting for result of Job2 and Job4
                val job2Result = d2.await()
                val job4Result = d4.await()
    
                // run Job5
                val d5 = asyncIO { job5(job2Result, job4Result) }
    
                // waiting for result of Job3
                val job3Result = d3.await()
    
                // run Job6
                val d6 = asyncIO { job6(job3Result, job4Result) }
    
                onDone(d5.await(), d6.await())
            }
        }
    
        private fun onDone(job5Result: String, job6Result: String) {
            // do something with result of Job5 and Job6
        }
    
    
        fun job1(): String {
            return "Result of job1"
        }
    
        fun job2(): String {
            return "Result of job2"
        }
    
        fun job3(): String {
            return "Result of job3"
        }
    
        fun job4(job1Result: String): String {
            return "Result of job4"
        }
    
        fun job5(job2Result: String, job4Result: String): String {
            return "Result of job5"
        }
    
        fun job6(job3Result: String, job4Result: String): String {
            return "Result of job6"
        }
    
        // extension function
        fun <T> CoroutineScope.asyncIO(ioFun: () -> T) = async(Dispatchers.IO) { ioFun() }
    }
    

    【讨论】:

    • 这真的很容易。好像我没有完全理解异步等待。现在我知道了,谢谢你。非常感谢
    • 嗨@Sergey,如何才能控制每个作业让假设我只想在所有作业正在执行时取消作业1,但不想干扰或妨碍其他作业的执行。跨度>
    • 嗨@Min2,您可以尝试致电d1.cancel() 取消作业。如果它也取消了父协程,请考虑使用 SupervisorJob 或 supervisorScope。还有关于结构化并发的有用链接:kotlinlang.org/docs/reference/coroutines/…
    • 由于某种原因,当我这样做时,只有第一个作业运行,第二个从不运行.. 我也没有返回值,但只想在 GlobalScope.launch 中运行 2 个作业,但第二个必须先完成后来。这导致第二个任务永远不会触发。有任何想法吗?附言。我使用 async{},因为 asyncIO 不存在
    猜你喜欢
    • 2020-09-02
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 2012-03-28
    相关资源
    最近更新 更多