Как запустить два задания параллельно, но дождаться завершения другого задания, используя сопрограммы kotlin - PullRequest
0 голосов
/ 25 декабря 2018

У меня есть следующие задания ниже:

  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?

Ответы [ 2 ]

0 голосов
/ 25 декабря 2018

Если это Android, вы можете сделать так, чтобы каждая подпрограмма отправляла трансляцию, когда она будет завершена.Другие подпрограммы получают трансляции, отмечают их и принимают меры, когда видят, что пора начинать.Если это не Android, я уверен, что вы можете сделать что-то подобное.

0 голосов
/ 25 декабря 2018

Это довольно просто.Все, что вам нужно сделать, это:

  1. Реализация CoroutineScope и создание CoroutineContext, или использование GlobalScope.
  2. Использование локального CoroutineScope или GlobalScope.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() }
}
...