假设有一个List,其中存储了分布式计算的作业的结果。
现在我有一个正在等待所有工作完成的主线程。
我知道在所有工作完成之前,List的大小需要。 scala中最优雅的方式是什么让主线程(while(true)loop)在作业完成时睡眠并让它清醒?
感谢您的回答
编辑:在尝试@ Stefan-Kunze的概念后没有成功(猜测我没注意到......)我举了一些代码示例:
第一个节点:
class PingPlugin extends SmasPlugin
{
val messages = new ListBuffer[BaseMessage]()
val sum = 5
def onStop = true
def onStart =
{
log.info("Ping Plugin created!")
true
}
def handleInit(msg: Init)
{
log.info("Init received")
for( a <- 1 to sum)
{
msg.pingTarget ! Ping() // Ping extends BaseMessage
}
// block here until all messages are received
// wait for messages.length == sum
log.info("handleInit - messages received: %d/%d ".format(messages.length, sum))
}
/**
* This method handles incoming Pong messages
* @param msg Pong extends BaseMessage
*/
def handlePong(msg: Pong)
{
log.info("Pong received from: " + msg.sender)
messages += msg
log.info("handlePong - messages received: %d/%d ".format(messages.length, sum))
}
}
第二个节点:
class PongPlugin extends SmasPlugin
{
def onStop = true
def onStart =
{
log.info("Pong Plugin created!")
true
}
/**
* This method receives Ping messages and send a Pong message back after a random time
* @param msg Ping extends BaseMessage
*/
def handlePing(msg: Ping)
{
log.info("Ping received from: " + msg.sender)
val sleep: Int = math.round(5000 * Random.nextFloat())
log.info("sleep: " + sleep)
Thread.sleep(sleep)
msg.sender ! Pong()
}
}
我猜这个解决方案可以用期货......
答案 0 :(得分:3)
挑选@jilen的方法:(此代码假设您的结果属于类型结果)
//just like lists futures can be yielded
val tasks: Seq[Future[Result]] = for (i <- 1 to results.size) yield future {
//results.size is the number of //results you are expecting
println("Executing task " + i)
Thread.sleep(i * 1000L)
val result = ??? //your code goes here
result
}
//merge all future results into a future of a sequence of results
val aggregated: Future[Seq[Result]] = Future.sequence(tasks)
//awaits for your results to be computed
val squares: Seq[Int] = Await.result(aggregated, Duration.Inf)
println("Squares: " + squares)
答案 1 :(得分:1)
在这里测试代码很难,因为我没有其他系统,但我会尝试。我假设所有这些都在Akka之下。
首先,像这样的阻塞表明了一个真正的设计问题。在演员系统中,您应该发送消息并继续前进。当返回正确的ping数时,您的日志命令应该在handlePong
。阻止init会挂起整个actor。你真的不应该这样做。
但是,好吧,如果你绝对必须这样做呢?那么这里的一个好工具就是ask pattern。像这样的东西(我不能检查这个编译没有更多的代码):
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._
...
implicit val timeout = Timeout(5 seconds)
var pendingPongs = List.empty[Future[Pong]]
for( a <- 1 to sum)
{
// Ask each target for Ping. Append the returned Future to pendingPongs
pendingPongs += msg.pingTarget ? Ping() // Ping extends BaseMessage
}
// pendingPongs is a list of futures. We want a future of a list.
// sequence() does that for us. We then block using Await until the future completes.
val pongs = Await.result(Future.sequence(pendingPongs), 5 seconds)
log.info(s"handlePong - messages received: ${pongs.length}/$sum")