但我如何检查演员是否退出?我可以很容易地想象自己有一个任务,主人演员开始一些工人演员,然后只是等待答案,每次检查这是否是最终答案(即任何演员是否仍在工作或他们都退出?)。
当然,我可以让他们都发回“我已经完成”的消息,然后计算它们,但这实际上并不令人满意。
测试完成工作人员时的最佳做法是什么?
修改#1 的
嘿伙计们,我正在调查期货,但遇到了麻烦。有人可以解释为什么这段代码不起作用:package test
import scala.actors.Futures._
object FibFut extends Application{
def fib(i:Int):Int =
if(i<2)
1
else
fib(i-1)+fib(i-2)
val f = future{ fib(3) }
println(f())
}
如果我在future-body中定义函数fib,它就有效。它必须是范围的东西,但我没有上面的任何错误,它只是挂起。任何人吗?
修改#2 的
似乎扩展应用程序并不是一个好方法。定义主要方法使一切正常。以下代码是我正在寻找的,所以期货竖起大拇指:)
package test
import scala.actors.Futures._
object FibFut {
def fib(i: Int): Int = if (i < 2) 1 else fib(i - 1) + fib(i - 2)
def main(args: Array[String]) {
val fibs = for (i <- 0 to 50) yield future { fib(i) }
for (future <- fibs) println(future())
}
}
答案 0 :(得分:3)
我个人喜欢“我已经完成”的粉丝;这是管理工作分配的好方法,作为奖励,你已经知道所有孩子什么时候完成了他们正在做的事情。
但是,如果您真的只想将某些工作一次并等待一切准备就绪,请查看scala.actors.Futures
。你可以要求它做一些计算:
val futureA = Futures.future {
val a = veryExpensiveOperation
(a,"I'm from the future!")
}
如果您提出了多个请求,那么您可以等待所有事情完成:
Futures.awaitAll(600*1000, futureA, futureB, futureC, futureD)
// Returns once all of A-D have been computed
val actualA = futureA() // Now we get the value
答案 1 :(得分:2)
前段时间我在Scala中链接actor时写了a post。 Actor链接是在Erlang,Scala Actors和其他actor库中监视actor的惯用[和最简单]方法。通过defalt,当你链接2个actor时,其中一个死亡,另一个立即死亡(除非演员陷阱/处理退出信号):
scala> case object Stop
defined module Stop
scala>
scala> val actor1 = actor {
| loop {
| react {
| case Stop =>
| println("Actor 1: stop")
| exit()
| case msg => println(msg)
| }
| }
| }
actor1: scala.actors.Actor = scala.actors.Actor$$anon$1@1feea62
scala>
scala> val actor2 = actor {
| link(actor1)
| self.trapExit = true
| loop {
| react {
| case msg => println(msg)
| }
| }
| }
actor2: scala.actors.Actor = scala.actors.Actor$$anon$1@1e1c66a
scala> actor1.start
res12: scala.actors.Actor = scala.actors.Actor$$anon$1@1feea62
scala> actor2.start
res13: scala.actors.Actor = scala.actors.Actor$$anon$1@1e1c66a
scala> actor1 ! Stop
Actor 1: stop
scala> Exit(scala.actors.Actor$$anon$1@1feea62,'normal) // Actor 2 received message, when Actor1 died
更复杂和灵活的方式是使用主管(Erlang中的主管行为,Akka Actors库中的 actor supervisors 等)。一个主管(本身就是一个演员)监视其他一些演员,并根据指定的策略重新启动它们(重新启动所有演员,如果一个演员死亡;重新启动只有一个演员,当它死亡时)。
答案 2 :(得分:0)
好的,大家,我已经提出了使用actor类的getState函数的解决方案。在解决方案中,我使用了这个主题的想法:Best method to peek into a Scala Actor's Mailbox 其中使用reactWithin(0)。我在使用react和loop时遇到了麻烦,程序只会阻止重大计算。这是通过将while(true)和reactWithin(int)替换为receiveWithin(int)来解决的。
我的解决方案如下(请注意,bigass代码块):
package test
import scala.actors._
import scala.actors.Actor.State._
case class Computation(index: Int, a: () ⇒ Int)
case class Result(i: String)
object Main {
def main(args: Array[String]) {
val m = new Master
m.start
}
}
class Master extends Actor {
val N = 40
var numberOfAnswers = 0
def fib(x: Int): Int =
if (x < 2)
1
else
fib(x - 1) + fib(x - 2)
val computers = for (i ← 0 to N) yield new Computer
def act {
for (i ← 0 until computers.size) {
computers(i).start
computers(i) ! Computation(i, () => fib(i))
}
println("done Initializing actors")
while (true) {
receiveWithin(1000) {
case Result(i) =>
val numberDone = computers.map(_.getState == Terminated).filter(_ == true).length
println(i)
numberOfAnswers += 1
case TIMEOUT =>
val allDone = computers.map(_.getState == Terminated).reduceRight(_ && _)
println("All workers done?:" + allDone)
println("# of answers:" + numberOfAnswers)
if (allDone)
exit()
}
}
}
}
class Computer extends Actor {
def act {
loop {
react {
case Computation(i, f) ⇒
sender ! Result("#" + i + " Res:" + f())
exit()
}
}
}
}
该程序计算斐波那契数(以最坏的方式)。这个想法只是测试多个线程对大型工作负载的利用率。以下行检查某个actor是否尚未终止:
computers.map(_.getState == Terminated).reduceRight(_ && _)
其中计算机的类型为IndexedSeq [Computer]。诀窍是使用TIMEOUT消息,我可以定期检查所有工作是否完成并采取相应措施(在这种情况下,当没有更多活动工人时退出)。我利用每个工人在退出之前发送结果的事实。通过这种方式,我知道我将始终收到结果并处理它们,然后才会显示为已终止。
当我使用react和loop而不是while(true)并接收时,有人可以评论程序“锁定”(停止接收消息)的事实吗?