【问题标题】:Scala actors and shared stateScala 演员和共享状态
【发布时间】:2011-02-12 23:35:05
【问题描述】:

我正在尝试实现一个调度程序参与者,它要么处理请求,要么在失败的情况下将处理委托给另一个参与者(实际上它是指数退避算法)。 Dispatcher Actor 有一个布尔变量,用于决定如何路由处理。

在actor中保持某种状态是否正确?可能会出现什么问题?我应该使用交易者(akka)还是 STM 来避免问题? (我正在使用 akka 演员)

class DispatcherActor extends Actor {

   var backoff = false

   def receive = {
    case SendMessage(registrationId, message) => {
      if (backoff) {
        //put on the queue
        backoffManagerActor ! AddMessageToQueue(message)
      } else {
        httpClient.sendNotificationToClient(message, this)
      }
    }
    case BackoffCompleted => //set backoff to false
      backoff = false
    }

   def otherMethod = {
      backoff=true
   } 
}

【问题讨论】:

  • 你不应该永远将你的actor实例传递给其他代码,它违反了Actor模型。传递 'self' 引用(ActorRef)并发回消息。

标签: scala shared-memory actor akka


【解决方案1】:

Actor 应该保持状态,但如果他们只是为了响应消息或其内部生成的操作而更改状态,那么最容易对它们进行推理;如果其他实体希望他们改变状态,他们应该发送消息。

在你的情况下,我会改变

def otherMethod { backoff = true }

到,在接收中,

case BeginBackoff => backoff = true

并让要调用 otherMethod 的人改为发送BeginBackoff。 (如果您需要优先处理退避消息,您应该使用两级接收其他人已经演示过,例如回答您之前关于演员的问题。)

【讨论】:

  • 其实otherMethod是httpclient执行的请求完成(nio)时调用的方法。这是一个监听器方法。我正在使用异步 http 客户端。那么我应该用消息传递替换侦听器方法吗? Actor 是按顺序处理消息还是同时处理消息?谢谢
  • Actors 按顺序处理消息,但如果你使用嵌套的receives/reacts,你可以优先从列表中挑选出某些消息。由于它是顺序的,因此您不必担心 BackoffCompleted 在设置 var 之后运行,即使它应该首先发生。因此,您可以让侦听器发送消息而不是设置布尔变量。但是,如果您知道自己可以避免这种混淆,则可以改用 java.util.concurrent.atomic.AtomicBoolean 而不是原始布尔值,以至少保持对布尔值的更新。
  • @Matroska - 我应该补充一点,如果这应该是超高性能并且您要频繁切换标志,您可能不希望消息传递的开销。 Scala 的演员表现不错,但他们肯定会在正确性和易于推理方面犯错,而不是表现。
猜你喜欢
  • 2019-10-07
  • 2019-04-23
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2011-01-20
  • 2011-01-30
相关资源
最近更新 更多