2011-03-04 88 views
5

我有一个演员正在将呼叫委派给有状态的单身人士。单身人士是有状态的,因为它保持着物体的地图。这个单例对象只用在actor和一个类(不是actor)中,我在这个map中检索一个对象(所以只是线程安全读取)。在阿卡·斯卡拉演员中使用单身人士

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) }     

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

回答

9

做,以任何理由在世界上。 相信我。

如果你需要那种事使用代理来代替,这是他们所擅长的:

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

+0

我已经解决了将地图放入演员和查询演员。所以这个单身人士已经被纳入演员,并且不会暴露任何东西。我开始认为演员和依赖注入不是好朋友。我对吗? – Matroska 2011-03-04 16:12:04

+2

DI工作得很好,我们甚至有一个Spring集成和一个Guice集成。 – 2011-03-05 00:06:13

+1

简单的解释会使这个更有用的答案。在问题中不遵循方法的原因是什么?为什么它不如说,封装在演员地图或使用代理? – mahonya 2015-09-18 16:56:11

3

从理论上讲,使用MyActorLogic,用一个简单的可变地图武装,从多个线程,可能会导致并发修改异常(当一个线程正在地图上,而另一个人修改它)。

你可以做到以下几点,以避免出现问题:

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

只是为了说明,真正的单身是:

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

我将按照第一个建议。我正在使用新的操作符,因为对象不能用于单元测试。但我也使用了蛋糕模式,所以我可能会用蛋糕模式来模拟对象。谢谢 – Matroska 2011-03-04 13:01:40

+0

我绝对不会赞同这样的。这只是乞求问题。 – 2011-03-04 15:11:18