我有一个线程从本地服务器接收数据包:
// Shared object:
@Volatile lateinit var recentPacket: Packet
val recvMutex = Object()
// Thread code:
thread(isDaemon = true) {
while (true) {
val packet = readPacket()
synchronized(recvMutex) {
recentPacket = packet
recvMutex.notifyAll()
}
}
}
我有多个其他线程等待数据包,每个线程都应该获得刚收到的相同数据包:
suspend fun receive() {
return synchronized(recvMutex) {
recvMutex.wait() // non-blocking alternative to this?
recentPacket
}
}
它可以工作,但Object.wait()
会阻止该线程。有没有办法避免这种情况?
答案 0 :(得分:1)
它可以工作,但
Object.wait()
会阻止该线程。有没有办法避免这种情况?
是的,但这意味着删除您现在使用的完整wait-notify
惯用语并将其替换为Kotlin的原生BroadcastChannel
。我还建议不要依赖默认的CommonPool
协程调度程序。这对原型代码来说是一个很好的方便,但在生产环境中你应该使用一个由你控制的线程池。
以下是一个基本示例,其中包含两个接收器和五个数据包:
import kotlinx.coroutines.experimental.asCoroutineDispatcher
import kotlinx.coroutines.experimental.channels.BroadcastChannel
import kotlinx.coroutines.experimental.channels.SubscriptionReceiveChannel
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
private val threadPool = Executors.newCachedThreadPool() as ExecutorService
val MyPool = threadPool.asCoroutineDispatcher()
fun main(args: Array<String>) {
val packetChannel = BroadcastChannel<Packet>(1)
(1..2).forEach {
launch(MyPool) {
receivePackets(it, packetChannel.openSubscription())
}
}
runBlocking {
(1..5).forEach {
packetChannel.send(Packet(it))
delay(100)
}
}
threadPool.shutdown()
}
suspend fun receivePackets(index: Int, packetChannel: SubscriptionReceiveChannel<Packet>) {
while (true) {
println("Receiver $index got packet ${packetChannel.receive().value}")
}
}
data class Packet(
val value: Int
)
期待看到这样的输出:
Receiver 1 got packet 1
Receiver 2 got packet 1
Receiver 2 got packet 2
Receiver 1 got packet 2
Receiver 1 got packet 3
Receiver 2 got packet 3
Receiver 1 got packet 4
Receiver 2 got packet 4
Receiver 1 got packet 5
Receiver 2 got packet 5
答案 1 :(得分:-1)
协同程序似乎处于试验状态;我建议在使用之前等到那些成熟。见https://kotlinlang.org/docs/reference/coroutines.html#experimental-status-of-coroutines
我的平均时间,您可以尝试ThreadPool
:
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.util.concurrent.Executors
import kotlin.concurrent.thread
fun start() {
val pool = Executors.newFixedThreadPool(10)
thread(isDaemon = true) {
val socket = DatagramSocket(12345)
while (!socket.isClosed) {
val packet = DatagramPacket(ByteArray(1000), 0)
socket.receive(packet)
pool.submit({
receive(packet)
})
}
}
pool.shutdown()
}
fun receive(packet: DatagramPacket) {
println(String(packet.data, 0, packet.length))
}
异步IO可能很有用;您可以查看Java Selectors