Nem*_*emo 2 kotlin kotlin-coroutines
我想挂起kotlin协程,直到从外部调用方法为止,就像旧的Java object.wait()和object.notify()方法一样。我怎么做?
在这里:正确地在Kotlin中实现wait and notify是如何使用Kotlin线程(阻塞)来实现这一点的答案。在这里:暂停协程直到条件为真才是如何使用CompleteableDeferreds做到这一点的答案,但我不想每次都必须创建一个新的CompleteableDeferred实例。
我目前正在这样做:
var nextIndex = 0
fun handleNext(): Boolean {
if (nextIndex < apps.size) {
//Do the actual work on apps[nextIndex]
nextIndex++
}
//only execute again if nextIndex is a valid index
return nextIndex < apps.size
}
handleNext()
// The returned function will be called multiple times, which I would like to replace with something like notify()
return ::handleNext
Run Code Online (Sandbox Code Playgroud)
来自:https : //gitlab.com/SuperFreezZ/SuperFreezZ/blob/master/src/superfreeze/tool/android/backend/Freezer.kt#L69
通道可用于此目的(尽管它们更通用):
当容量为0时,它将创建RendezvousChannel。该通道根本没有任何缓冲区。仅当发送和接收调用在时间上相遇(交会)时,元素才会从发送方转移到接收方,因此发送暂停,直到另一个协程调用接收,接收暂停,直到另一个协程调用send。
所以创造
val channel = Channel<Unit>(0)
Run Code Online (Sandbox Code Playgroud)
并使用channel.receive()for object.wait()和channel.offer(Unit)for object.notify()(或者send如果您想等到其他协程receive)。
对于notifyAll,您可以BroadcastChannel改用。
您当然可以轻松地封装它:
inline class Waiter(private val channel: Channel<Unit> = Channel<Unit>(0)) {
suspend fun doWait() { channel.receive() }
fun doNotify() { channel.offer(Unit) }
}
Run Code Online (Sandbox Code Playgroud)
可以为此使用基本suspendCoroutine{..}功能,例如
class SuspendWait() {
private lateinit var myCont: Continuation<Unit>
suspend fun sleepAndWait() = suspendCoroutine<Unit>{ cont ->
myCont = cont
}
fun resume() {
val cont = myCont
myCont = null
cont.resume(Unit)
}
}
Run Code Online (Sandbox Code Playgroud)
很明显,代码有问题,例如myCont字段未同步,预计sleepAndWait在之前调用resume等等,希望现在思路清晰。
Mutexkotlinx.coroutines 库中的类还有另一个解决方案。
class SuspendWait2 {
private val mutex = Mutex(locaked = true)
suspend fun sleepAndWait() = mutex.withLock{}
fun resume() {
mutex.unlock()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1026 次 |
| 最近记录: |