3

我需要一个很少更改的全局变量(单例)。实际上它只有在actor重新启动时才会改变,并重新初始化变量。由于我不能在伴生对象中使用单例 val 来执行此操作,因此我必须将其声明为 var(可变)。

object UserDatabase {
    var dbConnection = "" // initializing db connection
}

我阅读的许多指导方针总是反对共享可变状态。所以我将变量移动到类并使用消息传递来检索变量。

class UserDatabase extends Actor{
    val dbConnection = "" // initializing db connection locally
    def receive = {case GetConnection => self.reply(dbConnection)}
}

问题是,dbConnection 被许多..许多参与者非常频繁地访问,并且不断发送消息会降低性能(因为 akka 进程邮箱一个接一个)。

我不知道如何在不牺牲性能的情况下做到这一点。任何想法?

4

4 回答 4

3

也许改用代理?http://akka.io/docs/akka/1.2-RC6/scala/agents.html

于 2011-09-05T19:34:40.483 回答
2

首先,您是否实际测量/注意到性能下降?由于消息传递是轻量级的,因此对于您的应用程序来说可能已经足够快了。

然后,一个可能的解决方案:如果“全局”状态很少写入,但访问非常频繁,您可以选择推送策略。每次它发生变化时,UserDatabaseactor都会将更新后的值发送给感兴趣的actor。然后,您可以使用发布/订阅方法、依赖参与者注册、使用参与者池等。

class UserDatabase extends Actor{
    var dbConnection = "" // initializing db connection locally
    def receive = {
      case SetConnection( newConnection ) if dbConnection != newConnection => {
        dbConnection = newConnection
        sendUpdatedConnection(); // sends the change to every relevant actor
      }
    }
}
于 2011-09-05T15:18:34.273 回答
1

如果您在任何情况下都不需要经常使用该变量,则将其设置为 ajava.lang.concurrent.atomic.AtomicReference或将其每次访问都包装在一个synchronized块中(在变量上)可能会更简单、更有效。演员并不总是让事情变得更容易和更安全,只是通常情况下。

于 2011-09-05T16:42:08.377 回答
0
  1. 创建许多 Actor 作为 RoundRobinRouter 的路由。
  2. 让每个参与者处理一个连接并实际处理数据库逻辑。
于 2014-01-22T01:29:46.293 回答