依次运行Kotlin协程

时间:2020-10-19 08:47:42

标签: kotlin queue kotlin-coroutines

让我们说这些kotlin SUSPEND函数可以执行各种操作。

suspend fun operation1(){ //some code }
suspend fun operation2(){ //some code }
suspend fun operation3(){ //some code }
suspend fun operation4(){ //some code }
suspend fun operation5(){ //some code }

我有一个由外部库(我们无法修改)调用的函数,在该函数中调用这些函数。 (当然,它的逻辑实际上更复杂)。让我们假设该库可以在短时间内进行任意数量的调用。

fun calledByLibrary(someParam: String){
    GlobalScope.launch{
        when(someParam){
            "someValue1" -> operation1()
            "someValue2" -> operation2()
            "someValue3" -> operation3()
            "someValue4" -> operation4()
            "someValue5" -> operation5()
        }
    }
}

现在,我们有一个错误,指出无法将operation3和operation4挂起以在'paralel'中运行。它们甚至需要按照外部库调用的相同顺序执行。对于其他所有组合,都可以这样做,因此我们希望保留它们以使其暂停。

解决此问题的最佳方法是什么?

一种简单的方法是在operation3和operation4中使用Mutex,以确保它们不会同时运行,就像这样:

val mutex = Mutex()
suspend fun operation3(){ mutex.withLock(){/*some code*/} }
suspend fun operation4(){ mutex.withLock(){/*some code*/} }

但这不能保证它们将按照库请求的顺序执行。

也尝试在队列中搜索正在运行的协程,但令人惊讶的是没有发现任何琐碎的事情。 (当前解决方案是使用单线程调度程序和runBlocking,这远非理想)

1 个答案:

答案 0 :(得分:0)

在捆绑了很多东西之后,演员似乎可以解决问题,因为很多人提到使用渠道是演员的一部分。但是对于这样一个简单的问题,实现一个演员似乎是一个复杂的解决方案,所以我试图避免它,而是找到一个更简单的解决方案。

事实证明,通过在协程中使用相同的线程,可以轻松地固定互斥锁的概念,以确保执行顺序。 操作函数已经具有逻辑,可以在需要时使用适当的线程(如果没有,则添加一个琐碎的事情)。因此,唯一需要更改的是始终在同一线程的回调中启动协程。可以通过使用Dispachers.Unconfined轻松完成此操作,或者如果要避免这种情况,也可以创建自己的单线程Dispacher。

因此,当然是高度简化的解决方案,看起来像这样:

fun calledByLibrary(someParam: String){
    //You can use any single threaded dispatcher here
    //if you want to avoid the unconfined
    GlobalScope.launch(Dispachers.Unconfined){
        when(someParam){
            "someValue1" -> operation1()
            "someValue2" -> operation2()
            "someValue3" -> operation3()
            "someValue4" -> operation4()
            "someValue5" -> operation5()
        }
    }
}

val mutex = Mutex()
suspend fun operation1(){ launch{/*some code*/} }
suspend fun operation2(){ launch{/*some code*/} }
suspend fun operation3(){ mutex.withLock(){launch{/*some code*/}} }
suspend fun operation4(){ mutex.withLock(){launch{/*some code*/}} }
suspend fun operation5(){ launch{/*some code*/} }