5

ステートフル シングルトンへの呼び出しを委任しているアクターがいます。シングルトンはオブジェクトのマップを維持しているため、ステートフルです。このシングルトン オブジェクトは、アクターと、このマップで 1 つのオブジェクトを取得するクラス (アクターではない) でのみ使用されます (スレッド セーフな読み取りのみ)。

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

副作用/問題はありますか? ありがとう

4

2 に答える 2

9

世界で何らかの理由でそれをしないでください。私を信じて。

そのようなものが必要な場合は、代わりにエージェントを使用してください。

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

于 2011-03-04T15:11:51.753 に答える
3

理論的にはMyActorLogic、複数のスレッドから単純な変更可能なマップを使用して を使用すると、同時変更例外が発生する可能性があります (1 つのスレッドがマップをトラバースしているときに、別のスレッドがマップを変更している場合)。

問題を回避するために次のことを行うことができます。

  1. マップをアクターに入れます (プライベート メンバーとして)。ではAkkaActorインスタンスを直接操作するのではなく、プロキシ経由でインスタンスにアクセスしますActorRef。この場合、マップへの安全なアクセスは、常に一度に 1 つのメッセージを処理するアクターによって保証されるだけではありません。他のスレッドは、リフレクションを介してもプライベート メンバーにアクセスできません。
  2. MyActorLogicスレッドセーフなupdate/retrieve メソッドを作成できます (たとえば、それらを作成しますsynchronized) 。
  3. 古き良きものをお使いいただけますConcurrentHashMap
  4. 代わりにval map:mutable.Mapを使用できますvar map:immutable.Map。したがって、複数のスレッドがアクセスするmapと、古いデータが処理される場合がありますが、同時に変更が行われることはありません (コピー オン ライト アプローチ)。

念のため、真のシングルトンは次のようになります。

object MyActorLogic{
 val map:Map[String, Object] = Map()
 ...
于 2011-03-04T08:26:37.993 に答える