同步创建Akka actor

时间:2018-02-27 15:50:54

标签: java scala akka

我正在使用ActorSystem.actorOf(property, bla)创建一个演员。问题在于,由于默认情况下Akka异步创建了actor,所以我遇到了竞争条件。

有没有办法同步在Akka中创建一个演员?

1 个答案:

答案 0 :(得分:2)

在最简单的用例中,您可以简单地采用这种模式:

  1. 在您的actor的preStart中,您初始化一个长时间运行的异步任务
  2. 完成后,您将向自己发送一条消息,其中包含长时间运行任务的结果
  3. 处理此结果时,初始化actor的状态。
  4. 您还需要一条订阅消息:当actor接收到其状态时,如果它被初始化,则立即回答,如果没有将发送者附加到订阅者列表。处理初始化结果(3)时,您还会通知所有订阅者。

    trait ExpensiveThing
    import MyActor._
    class MyActor extends Actor {
    
      var expensiveThing : ExpensiveThing = null
      var initializationListeners:List[ActorRef] = List.empty
    
    
      def initializeExpensiveThing() : Future[ExpensiveThing]  = ???
    
      override def preStart(): Unit = {
        initializeExpensiveThing onSuccess  {
          case s => self ! InitializationDone(s)
        }
    
      }
    
      override def receive: Receive = {
        case InitializationDone(s) =>
          expensiveThing = s
          initializationListeners.foreach{ s => s ! Initialized }
        case SubscribeInitialization =>
          if(expensiveThing != null){
            sender ! Initialized
          }
          else {
            initializationListeners = sender() +: initializationListeners
          }
    
      }
    
    
    }
    
    object MyActor{
      case class InitializationDone(s:ExpensiveThing)
    
      case object SubscribeInitialization
    
      case object Initialized
    
    
    }
    object MyProgram {
      def doSomething(actorSystem:ActorSystem)  = {
        val actor = actorSystem.actorOf(Props(new MyActor))
        import akka.pattern.ask
        implicit val inizializationTimeout = new Timeout(100,TimeUnit.SECONDS)
        Await.result(actor ? SubscribeInitialization,Duration.Inf)
      }
    }
    

    注意:

    1. 我强烈反对你不做Await.result,你应该简单地对将来使用ask模式时返回的flatMap进行讨论
    2. 应使用context.become或Akka提供的FSM抽象来处理更复杂的生命周期。