不知道如何命名这个帖子,但会尝试用几行来解释这个问题。
我有一个命令需要计算所需日期范围的价格。要计算它,系统需要单独获取每天的价格(数据库,配置,缓存,无论从哪里开始)。
我的建议是让一个PriceRangeActor有一个DailyPriceActors池,并向他们发送像CalculateDailyPrice这样的命令。
但是如何在PriceRanceActor中组装所有数据?
1。 有一些复杂键的大地图只是闻起来很多。如何确定范围是否完全计算?有没有更简单的方法呢?
2。 为每个命令创建新的PriceRangeActor并使用ask模式查询DailyPriceActors列表?
答案 0 :(得分:1)
因为你没有使用任何消息传递/排队我建议使用Futures而不是Actors作为你的并发抽象机制。这个blog entry提出了一个非常有说服力的论点,即Actors用于状态,而Futures用于计算。
使用期货或演员?
(这是一个未来),你可以使用Future.sequence
将所有单独的查询期货捆绑在一起,只有在所有子查询都完成后才能完成完整。
使用期货(推荐)
import scala.concurrent.Future
object Foo extends App {
type Date = Int
type Prices = Seq[Float]
type PriceMap = Map[Date, Prices]
//expensive query function
def fetchPrices(date : Date) : Prices = ???
//the Dates to query Prices for
val datesToQuery : Seq[Date] = ???
import scala.concurrent.ExecutionContext.Implicits._
def concurrentQuery(date : Date) : Future[Prices] = Future {fetchPrices(date)}
//launches a Future per date query, D Dates => D Futures
//Future.sequence converts the D Futures into 1 Future
val dates2PricesFuture : Future[PriceMap] =
Future.sequence(datesToQuery map concurrentQuery)
.map(datesToQuery zip _)
.map(_.toMap)
dates2PricesFuture onSuccess { case priceMap : PriceMap =>
//process the price data which is now completely available
}
}//end object Foo
使用ACTORS
import scala.concurrent.Future
import akka.actor.{Actor, ActorSystem, Props}
import akka.pattern.ask
import akka.util.Timeout
object Foo extends App {
type Date = Int
type Prices = Seq[Float]
type PriceMap = Map[Date, Prices]
def fetchPrices(date : Date) : Prices = ???
val datesToQuery : Seq[Date] = ???
class QueryActor() extends Actor {
def receive = { case date : Date => sender ! fetchPrices(date) }
}
implicit val as = ActorSystem()
implicit val queryTimeout = Timeout(1000)
import as.dispatcher
def concurrentQuery(date : Date) : Future[Prices] =
ask(as actorOf Props[QueryActor],date).mapTo[Prices]
val dates2PricesFuture : Future[PriceMap] =
Future.sequence(datesToQuery map concurrentQuery)
.map(datesToQuery zip _)
.map(_.toMap)
dates2PricesFuture onSuccess ... //same as first example
}//end object Foo