根据此文档,Kotlin不鼓励使用wait
和notify
:https://kotlinlang.org/docs/reference/java-interop.html
等待()/通知()
有效的Java Item 69请建议更喜欢并发实用程序来wait()和notify()。因此,这些方法不适用于Any类型的引用。
然而,该文件没有提出任何正确的方法。
基本上,我想实现一个服务,它将读取输入数据并处理它们。如果没有输入数据,它将暂停,直到有人通知有新的输入数据。像
这样的东西while (true) {
val data = fetchData()
processData(data)
if (data.isEmpty()) {
wait()
}
}
编辑:
我不想使用这些不推荐的方法(反模式),我真的想知道如何正确地做到这一点。
在我的情况下fetchData
从数据库中读取数据,因此不能使用我的情况下的队列。
答案 0 :(得分:19)
通常,您应尽可能使用更高级别的并发实用程序。
但是,如果没有高级构造在您的情况下工作,则直接
更换是使用一个
ReentrantLock
和一个
Condition
在那个锁上。
例如,如果您的Java代码类似于:
private Object lock = new Object();
...
synchronized(lock) {
...
lock.wait();
...
lock.notify();
...
lock.notifyAll();
...
}
您可以将其更改为以下Kotlin:
private val lock = ReentrantLock()
private val condition = lock.newCondition()
lock.withLock { // like synchronized(lock)
...
condition.await() // like wait()
...
condition.signal() // like notify()
...
condition.signalAll() // like notifyAll()
...
}
虽然这稍微冗长一些,但条件确实提供了额外的一些
灵活性,因为你可以在一个锁上有多个条件
也是其他类型的锁(特别是ReentrantReadWriteLock.ReadLock
和
ReentrantReadWriteLock.WriteLock
)。
请注意withLock
是Kotlin提供的扩展函数,负责在调用提供的lambda之前/之后调用Lock.lock()
/ Lock.unlock()
。
答案 1 :(得分:14)
对于您的用例,BlockingQueue
可以是一个合适的高级并发实用程序,但应用它需要了解和修改您的代码结构。
这个想法是,fetchData()
应该.take()
队列中的一个项目,如果队列为空,那将阻止执行,直到项目出现,这将消除.wait()
in你的代码。数据生产者应将.put(t)
数据放入队列。
如果确实需要使用wait
和notify
,例如为了在低级实现并发实用程序,您可以将Kotlin对象强制转换为java.lang.Object
并在之后调用这些函数,如the language reference中所述。或者,写为扩展函数:
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
private fun Any.wait() = (this as java.lang.Object).wait()
答案 2 :(得分:0)
您可以使用kotlin Mutex来暂停协程而不是阻塞线程:
Intents.init()
以下是一个运行示例:https://pl.kotl.in/Q6V0X8DvL。
但是我更喜欢使用冷 Flow或 hot Channel来解决此问题。 article这里是关于伟大的罗马伊莱莎洛夫的冷流和热通道的很好的{@ 3}