所有Scala期货都已完成

时间:2015-03-15 22:04:39

标签: scala future

我有一个akka演员,我在scala中有几个未来只做一些额外的工作并将计算保存到共享变量中。主要工作完成后,我想等待这些额外的工作。期货并回答答案。简单的代码是这样的:

....
val replyTo = sender()
var informationCollector = InformationCollector()
val mainFuture: Future[GetMainInformation] = ...
val aFuture: Future[GetExtraInformationA] =...
val bFuture: Future[GetExtraInformationB] =...
val cFuture: Future[GetExtraInformationC] =...

// now I want all the futures to write their result
// and save it into the informationCollector and then
// after all have executed, reply back to Sender all the collected Data.

通过这种方法,我有2个问题。我不确定在期货的onSuccess调用中访问InformationCollector是否安全,我也希望能够轻松扩展(因此可以轻松添加其他收集器)。

到现在为止,我提出了这个解决方案,但我不确定它是否正确

// IMPORTANT: firstly add map for all of the extraInfoFutures to add that information into collector
// this will create aFutureMapped, bFutureMapped, cFutureMapped
roomFuture onComplete {
      case Success(mainInfo: GetMainInformation) => {
           informationCollector = informationCollector.copy(mainInformation=mainInfo)
           Future.sequence(List(aFutureMapped,bFutureMapped,cFutureMapped)) onComplete { _ =>
               replyTo ! informationCollector
           }

      }
}

任何帮助都非常感谢。

1 个答案:

答案 0 :(得分:1)

我不确定我是否完全理解你的问题但我至少可以在第一期提供答案。

onComplete中访问可变状态可能不安全。实际上它会使演员的整个目的无效。如果您访问可变状态,则应始终通过actor的邮箱进行操作,例如self ! ModifyState(newValue)

这里的问题是onComplete方法与actor不在同一个线程中导致可能有两个线程同时修改相同数据的情况,因此改变状态会产生所有相同的问题并发状态突变(竞争条件等)。

对于第二个问题,我只会通过self ! TypeAExtraValue(someValue)从不同类型的额外期货中收集值,然后在收到所有额外值后发送收集器(例如TypeAInfoCollector)。正确使用时,actor会删除此问题,因为它们一次只处理一条消息。

代码看起来像这样:

val extraInfoFuture = getExtraInfo()
val infoCollector = new Collector()

extraInfoFuture onComplete {
  case Success(extraInfo) => self ! ExtraInfo(extraInfo) 
}

...

def receive = {
  case ExtraInfo(info) => {
    infoCollector.collect(info)
    if(infoCollector.collectedAll) sender() ! infoCollector
  }
}