sarah w
sarah w

Reputation: 3485

how to use synchronization in scala

I am creating an actor and I want to create it the first time and then use its actor reference whenever that actor is needed. Here is the code

val actorPath = "akka://testActorSystem/user/'"
object ActorManager {  
def getTestActorRef: ActorRef = {
    var actorRef: Option[ActorRef] = None
    this.synchronized {
    val sel = system.actorSelection(actorPath + "testActor");
    val future1 = sel.resolveOne()
    val res: Try[ActorRef] = Await.ready(future1, timeout.duration).value.get
    res match {
      case Success(actorref) =>
        actorRef = Some(actorref)
        actorRef.get
      case Failure(e) =>
        val testActor = system.actorOf(Props[TestActor], name = "testActor")
        actorRef = Some(testActor)
    }
    getActorRef(actorRef.get)
    }
    actorRef.get
  }
}

Q1->Is that the right way to achieve my desired functionality? The problem I am having is whenever this code is called in two places at the same time.

ActorManager.getTestActorRef

it throws two different exceptions:

akka.actor.ActorNotFound: Actor not found for: ActorSelection[Anchor(akka://testActorSystem/), Path(/user/'testActor)]
        at akka.actor.ActorSelection$$anonfun$resolveOne$1.apply(ActorSelection.scala:65) ~[akka-actor_2.11-2.3.6.jar:na]
        at akka.actor.ActorSelection$$anonfun$resolveOne$1.apply(ActorSelection.scala:63) ~[akka-actor_2.11-2.3.6.jar:na]

and:

akka.actor.InvalidActorNameException: actor name [testActor] is not unique!
        at akka.actor.dungeon.ChildrenContainer$NormalChildrenContainer.reserve(ChildrenContainer.scala:130) ~[akka-actor_2.11-2.3.6.jar:na]
        at akka.actor.dungeon.Children$class.reserveChild(Children.scala:77) ~[akka-actor_2.11-2.3.6.jar:na]
        at akka.actor.ActorCell.reserveChild(ActorCell.scala:369) ~[akka-actor_2.11-2.3.6.jar:na]

I tried to use this.synchronized but it did not help, the problem arises when I am invoking this method more than once

ActorManager.getTestActorRef

How can I create actor once and use its actorRef again and again without creating it again?

Upvotes: 0

Views: 305

Answers (1)

Evgeny
Evgeny

Reputation: 1770

To achieve your goal you just need:

object ActorManager {
  val getTestActorRef: ActorRef = system.actorOf(Props[TestActor], name = "testActor")
}

this will create actor once and it will be available. You do not need all these thing with actorSelection, synchronized and so on.

So you will get static reference to ActorRef you can use to send messages. Actor for this reference will be created once in background.

Upvotes: 3

Related Questions