我正在使用RXTX库将一些数据发送到串口。发送数据后,我必须等待1秒钟才能收到ACK。我使用ArrayBlockingQueue实现了这个功能:
例如
val queue = ArrayBlockingQueue(1)
def send(data2Send : Array[Byte]) : Array[Byte]{
out.write(data2Send)
queue.poll(1000)
}
def receive(receivedData : Array[Byte]){
queue.add(receivedData)
}
这非常有效,但是因为我正在学习Scala,所以我想使用Actors来处理线程和锁定结构。
我的第一次尝试如下:
class Serial {
sender = new Sender(...)
new Receiver(...).start
class Sender {
def send(data2Send : Array[Byte]) : Array[Byte]{
out.write(data2Send)
receiveWithin(WAIT_TIMEOUT_MILLIS) {
case response => response
case TIMEOUT => null
}
}
}
class Receiver extends Actor{
def act{
loop{
sender ! read()
}
}
}
}
但是这段代码抛出了一个java.lang.AssertionError:断言失败:从属于其他actor的频道接收。我认为问题在于我无法使用接收或在行为定义之外做出反应。我正在遵循的方法是正确的吗?
第二次尝试:
class Serial {
new Sender(...).start
new Receiver(...).start
def send() = (sender ?! data2Send).asInstanceOf(Array[Byte])
class Sender {
def act() {
loop{
receive{
out.write(data2Send)
receiveWithin(WAIT_TIMEOUT_MILLIS) {
case response => response
case TIMEOUT => null
}
}
}
}
}
class Receiver extends Actor{
def act{
loop{
sender ! read()
}
}
}
}
在第二次尝试中,我得到java.util.NoSuchElementException:发送者时空列表的头部! read()行被执行。它看起来更复杂
答案 0 :(得分:1)
除非您使用的是NIO,否则在这种情况下无法避免阻止。最终你的消息来自你需要read()
的套接字(即某个线程,某处,必须阻止)。
看看你的3个例子(即使假设它们都有效),如果你在六个月的时间凌晨2点发现了一个错误,那么你认为你更愿意看?我知道我会选择哪一个!
演员非常适合在事件驱动的系统周围发送异步消息。如果您点击了一些使用套接字的外部API,您可以在其周围包含类似actor的 facade ,以便它们可以与系统的其他部分进行交互(以便保护系统的其余部分不受了解实施细节)。一些指示:
对于必须处理读/写插座的实际演员,保持简单。
尝试并组织系统,以便与此演员的通信是异步(即其他演员不会阻止并等待回复)
鉴于scala actor库即将被弃用,我将开始使用 akka