是否可以接收或响应行为功能之外的消息?

时间:2012-06-26 18:36:34

标签: scala actor

我正在使用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()行被执行。它看起来更复杂

1 个答案:

答案 0 :(得分:1)

除非您使用的是NIO,否则在这种情况下无法避免阻止。最终你的消息来自你需要read()的套接字(即某个线程,某处,必须阻止)。

看看你的3个例子(即使假设它们都有效),如果你在六个月的时间凌晨2点发现了一个错误,那么认为你更愿意看?我知道我会选择哪一个!

演员非常适合在事件驱动的系统周围发送异步消息。如果您点击了一些使用套接字的外部API,您可以在其周围包含类似actor的 facade ,以便它们可以与系统的其他部分进行交互(以便保护系统的其余部分不受了解实施细节)。一些指示:

  • 对于必须处理读/写插座的实际演员,保持简单

  • 尝试并组织系统,以便与此演员的通信是异步(即其他演员不会阻止并等待回复)

  • 鉴于scala actor库即将被弃用,我将开始使用 akka