【问题标题】:How to make coroutines run in sequence from outside call如何使协程从外部调用按顺序运行
【发布时间】:2019-04-01 13:44:56
【问题描述】:

我是协程及其工作原理的真正新手,我已经阅读了很多关于它的内容,但我似乎无法理解如何或是否可以实现我的最终目标。

我会尽量详细解释。无论如何,这是我的目标:

Ensure that coroutines run sequentially when a method that has said coroutine is called.

我创建了一个符合我希望发生的测试:

class TestCoroutines {

  @Test
  fun test() {
    println("Starting...")

    runSequentially("A")
    runSequentially("B")

    Thread.sleep(1000)
  }

  fun runSequentially(testCase: String) {
    GlobalScope.launch {
      println("Running test $testCase")
      println("Test $testCase ended")
    }
  }
}

重要提示:我无法控制有人调用runSequentially 函数的次数。但我想保证它会按顺序调用。

此测试运行以下输出:

Starting...
Running test B
Running test A
Test A ended
Test B ended

Starting...
Running test A
Running test B
Test B ended
Test A ended

This is the output I want to achieve :
Starting...     
Running test A
Test A ended
Running test B
Test B ended

我想我明白为什么会发生这种情况:每次我调用 runSequentially 时,我都会创建一个新的 Job,它正在运行,并且异步运行。

如果我们无法控制协程被调用的次数,协程是否可以保证它们只会在前一个(如果它正在运行)完成后运行?

【问题讨论】:

  • 有一种非常简单的方法可以实现所需的输出:使用runBlocking 而不是launch。否则,实际上并没有“前一个协程”的概念,因此“保证它们只会在前一个(如果它正在运行)完成后运行”还不清楚。您能指定测试中允许更改的内容吗?
  • runBlocking 确实实现了所需的输出,但它阻塞了主线程,在我的用例中它不可能发生。

标签: kotlin kotlin-coroutines


【解决方案1】:

您正在寻找的是对请求进行排序的队列和为它们提供服务的工作人员的组合。总之,你需要一个actor

private val testCaseChannel = GlobalScope.actor<String>(
        capacity = Channel.UNLIMITED
) {
    for (testCase in channel) {
        println("Running test $testCase")
        println("Test $testCase ended")
    }
}

fun runSequentially(testCase: String) = testCaseChannel.sendBlocking(testCase)

【讨论】:

    猜你喜欢
    • 2014-06-04
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2012-11-08
    • 2022-08-19
    • 2019-04-13
    • 2020-07-23
    • 1970-01-01
    相关资源
    最近更新 更多