如何使用 actor 重写具有共享依赖项的 for 循环
我们有一些代码需要运行得更快。它已经被分析过,所以我们想使用多个线程。通常我会设置一个内存队列,并让许多线程获取队列的作业并计算结果。对于共享数据,我将使用 ConcurrentHashMap 或类似的。
我真的不想再走那条路了。根据我的阅读,使用 actor 会产生更干净的代码,如果我使用 akka,迁移到 1 个以上的 jvm 应该会更容易。这是真的吗?
然而,我不知道如何思考演员,所以我不知道从哪里开始。
为了更好地了解这个问题,这里有一些示例代码:
case class Trade(price:Double, volume:Int, stock:String) {
def value(priceCalculator:PriceCalculator) =
(priceCalculator.priceFor(stock)-> price)*volume
}
class PriceCalculator {
def priceFor(stock:String) = {
Thread.sleep(20)//a slow operation which can be cached
50.0
}
}
object ValueTrades {
def valueAll(trades:List[Trade],
priceCalculator:PriceCalculator):List[(Trade,Double)] = {
trades.map { trade => (trade,trade.value(priceCalculator)) }
}
def main(args:Array[String]) {
val trades = List(
Trade(30.5, 10, "Foo"),
Trade(30.5, 20, "Foo")
//usually much longer
)
val priceCalculator = new PriceCalculator
val values = valueAll(trades, priceCalculator)
}
}
如果有使用 Actor 经验的人能够建议这如何映射到 Actor,我将不胜感激。
We have some code which needs to run faster. Its already profiled so we would like to make use of multiple threads. Usually I would setup an in memory queue, and have a number of threads taking jobs of the queue and calculating the results. For the shared data I would use a ConcurrentHashMap or similar.
I don't really want to go down that route again. From what I have read using actors will result in cleaner code and if I use akka migrating to more than 1 jvm should be easier. Is that true?
However, I don't know how to think in actors so I am not sure where to start.
To give a better idea of the problem here is some sample code:
case class Trade(price:Double, volume:Int, stock:String) {
def value(priceCalculator:PriceCalculator) =
(priceCalculator.priceFor(stock)-> price)*volume
}
class PriceCalculator {
def priceFor(stock:String) = {
Thread.sleep(20)//a slow operation which can be cached
50.0
}
}
object ValueTrades {
def valueAll(trades:List[Trade],
priceCalculator:PriceCalculator):List[(Trade,Double)] = {
trades.map { trade => (trade,trade.value(priceCalculator)) }
}
def main(args:Array[String]) {
val trades = List(
Trade(30.5, 10, "Foo"),
Trade(30.5, 20, "Foo")
//usually much longer
)
val priceCalculator = new PriceCalculator
val values = valueAll(trades, priceCalculator)
}
}
I'd appreciate it if someone with experience using actors could suggest how this would map on to actors.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是对我对昂贵计算的共享结果的评论的补充。这是:
这是一个用法示例:
This is a complement to my comment on shared results for expensive calculations. Here it is:
Here's an usage example:
对于简单的并行化,我会抛出一堆工作来处理,然后等待它们全部返回,我倾向于使用 Futures 模式。
基本上,这个想法是创建一组工作人员(每个工作负载一个),然后将所有数据扔给他们!这立即回馈了未来。当您尝试读取未来时,发送方会阻塞,直到工作人员实际完成数据处理。
您可以重写上面的代码,以便
PriceCalculator
扩展Actor
,而valueAll
协调数据的返回。请注意,传递非不可变数据时必须小心。
不管怎样,在我输入的机器上,如果你运行上面的代码,你会得到:(
显然我至少有四个核心;并行计时有点不同,具体取决于哪个工作人员获得什么处理器以及其他正在发生的事情机器。)
For simple parallelization, where I throw a bunch of work out to process and then wait for it all to come back, I tend to like to use a Futures pattern.
Basically, the idea is to create a collection of workers--one per workload--and then throw all the data at them with !! which immediately gives back a future. When you try to read the future, the sender blocks until the worker's actually done with the data.
You could rewrite the above so that
PriceCalculator
extendedActor
instead, andvalueAll
coordinated the return of the data.Note that you have to be careful passing non-immutable data around.
Anyway, on the machine I'm typing this from, if you run the above you get:
(Obviously I have at least four cores; the parallel timing varies rather a bit depending on which worker gets what processor and what else is going on on the machine.)