【问题标题】:Use singletons in akka scala actor在 akka scala 演员中使用单例
【发布时间】:2011-07-08 12:38:10
【问题描述】:

我有一个演员将调用委托给有状态的单例。单例是有状态的,因为它维护着一个对象映射。这个单例对象仅在actor和一个类(不是actor)中使用,我在该映射中检索一个对象(因此只是线程安全读取)。

class MyActor extends Actor{
  def receive()={
    case ACase => singleton.amethod()  
    case BCase => singleton.bmethod()
     }
 }

val singleton = new MyActorLogic

class MyActorLogic{
 val map:Map[String, Object] = Map()
 def amethod()=//alter the map

 def readMap(value:String) = map(value)    }                

会不会有任何副作用/问题? 谢谢

【问题讨论】:

    标签: multithreading scala actor akka


    【解决方案1】:

    不要不要出于任何原因这样做。 相信我。

    如果您需要那种东西,请改用 Agent,这就是它们的好处:

    http://doc.akka.io/docs/akka/2.0.4/scala/agents.html

    【讨论】:

    • 我已经解决了将地图放入演员并查询演员。所以单例已经被合并到了actor里面,并没有暴露任何东西。我开始认为演员和依赖注入不是好朋友。我说的对吗?
    • DI 工作得很好,我们甚至有一个 Spring-integration 和一个 Guice-integration。
    • 一个简短的解释将使这成为一个更有用的答案。不遵循问题中的方法的原因是什么?为什么不如将地图封装在actor中或使用Agents?
    • 您能否解释一下您热情建议背后的原因,以避免 OP 的初始实施,@ViktorKlang?
    • 当前版本的 Akka 2.5.1 表明代理将在未来的版本中被弃用 doc.akka.io/docs/akka/2.5.1/scala/agents.html 如果你能更新你的答案以反映当前的发展,那就太好了。
    【解决方案2】:

    理论上,使用MyActorLogic,配备一个简单的可变映射,来自多个线程,可能会导致并发修改异常(当一个线程正在遍历映射,而另一个线程正在修改它时)。

    您可以执行以下操作以避免出现问题:

    1. 将地图放入actor(作为私人成员)。在Akka 中,您不是直接使用Actor 实例(而是通过代理-ActorRef 访问它)。在这种情况下,对地图的安全访问不仅由参与者保证,而且始终一次处理一条消息 - 其他线程即使通过反射也无法访问私有成员。
    2. 您可以使MyActorLogic 的更新/检索方法成为线程安全的(例如,使它们成为synchronized
    3. 你可以用老好ConcurrentHashMap
    4. 您可以使用var map:immutable.Map 代替val map:mutable.Map。因此,访问map 的多个线程可能偶尔会处理陈旧数据,但不会有并发修改(写时复制方法)。

    只是为了说明,真正的单例应该是:

    object MyActorLogic{
     val map:Map[String, Object] = Map()
     ...
    

    【讨论】:

    • 我会遵循第一个建议。我正在使用 new 运算符,因为对象对于单元测试是不可模拟的。但我也在使用蛋糕图案,所以我可能能够用蛋糕图案模拟对象。谢谢
    • 我永远不会支持这样的事情。它只是在乞求问题。
    猜你喜欢
    • 2013-06-16
    • 2019-04-23
    • 2014-06-13
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多