如何使用Kotlin协程并行运行两个作业,但等待另一个作业完成

时间:2018-12-25 10:27:50

标签: kotlin parallel-processing coroutine

我下面有这些工作:

  1. 异步放大复杂的日历视图
  2. 下载事件A
  3. 下载事件B
  4. 将日历视图添加到其父视图
  5. 将事件添加到日历
  6. 将B事件添加到日历

我想要

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

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

如何使用Kotlin协程实现这些功能?

2 个答案:

答案 0 :(得分:3)

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

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

您可以将下一个代码应用于算法(所有说明都在注释中):

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() }
}

答案 1 :(得分:-2)

如果是Android,则可以让每个例程在完成后发送广播。其他例程获取广播,将其标记为下来,并在看到开始时采取措施。 如果不是Android,我相信您可以做类似的事情。