如何强制 2 个协程不同时运行

问题描述 投票:0回答:2

在此代码中:

private suspend fun doSthSingleThreaded(){
    coroutineScope {
        //Coroutine 1
        launch {
            //do sth that will suspend
        }
        //Coroutine 2
        launch {
            //Do sth else that will suspend too
        }
    }
}

有没有办法让这两个协程的行为就像它们共享底层线程一样?这就是我希望它工作的方式(我想以它们都使用 threadA 的方式调整代码):

  • 协程 1 在线程 A 上运行(协程 2 被挂起)
  • 协程 1 暂停,协程 2 在线程 A 上运行
  • 协程 2 完成了它的工作,协程 1 继续在 threadA 上工作,直到完成,然后函数返回。

编辑: 这是 Y 我想这样做: 我有一个 SharedFlow,它在某种程度上是我从串行端口接收到的所有数据的单一事实来源。

val hotFlow = SharedFlow<String> //buffer = ALot, replay = 0

每当我向该端口写入任何内容时,我都会从这里读取它的答案。像这样:

port.writeSth()
val answer = hotFlow.first {it == "OK" || it == "ERROR"}
if(answer == "OK") return
//process error

上面代码(replay = 0)的问题是 HotFlow 有时会返回一个响应,然后很快返回其他内容,以至于我无法捕捉到我的答案!

为什么重播=0?我写入此端口的所有不同命令都有答案“OK”或“ERROR”,并且该端口不会返回任何说明此答案属于哪个命令的内容。所以如果重播!= 0:

port.writeSth()
val portCache = hotFlow.replay
//Now how do I know if the last item is my answer or I should still wait?

所以我想也许我可以:

launch{
val answer = hotFlow.first{it == "OK" || it == "ERROR" }
//process answer
}
launch{
port.writeSth()
}

执行顺序:

  1. 从端口收集所有内容并暂停
  2. 写点东西
  3. 第一个挂起的协程肯定能抓住答案
kotlin concurrency coroutine
2个回答
1
投票

您可以使用 newSingleThreadContext 获得单线程绑定的协程调度程序,但请小心:

专用线程是非常昂贵的资源。在真实的应用程序中,当不再需要时,必须使用 close 函数释放它,或者将其存储在顶级变量中并在整个应用程序中重用。

如果您只需要限制并行性,则可以使用 limitedParallelism 代替:

Dispatchers.Default.limitedParallelism(1)
。这并不能保证协程总是使用同一个线程,只能保证最多同时执行一个协程。

private suspend fun doSthSingleThreaded() {
    val confined = newSingleThreadContext("My Thread")
//    or
//    val confined = Dispatchers.Default.limitedParallelism(1)
    coroutineScope {
        //Coroutine 1
        launch(confined) {
            //do sth that will suspend
        }
        //Coroutine 2
        launch(confined) {
            //Do sth else that will suspend too
        }        
    }
}

-1
投票

在我的游戏应用程序中,我有四个角色,当它们全部上传时,我会显示角色。我在同一线程(Dispatcher.IO 线程)中获取所有字符。然后我等待一切。在这里,所有角色都开始同时上传。如果先上传字符2,则等待另外3个字符。当全部上传后,它会返回字符列表。如果其中任何一个无法上传,则不会返回字符列表。

withContext(Dispatchers.IO) {
    val characterList = listOf( async {
            getCharacter(firstModel)
        }, async {
            getCharacter(secondModel)
        }, async {
            getCharacter(thirdModel)
        }, async {
            getCharacter(lastModel)
        })
    val characters = characterList.awaitAll()
    return Resource.success(
        characters
    )
}
© www.soinside.com 2019 - 2024. All rights reserved.