我有一个如下的异步控制流:
ActorA ! DoA(dataA, callback1, callbackOnErrorA)
def callback1() = {
...
ActorB ! DoB(dataB, callback2, callbackOnErrorB)
}
def callback2() = {
ActorC ! DoC(dataC, callback3, callbackOnErrorC)
}
...
我如何将这个流分成几个部分(延续),并在保持整体状态的同时将这些流分配给不同的参与者(或线程/任务)?
任何暗示都表示赞赏,谢谢
答案 0 :(得分:9)
我喜欢使用scalaz.concurrent.Promise
。这个例子与你问题中的例子不完全相同,但它给你的想法。
object Async extends Application {
import scalaz._
import Scalaz._
import concurrent._
import concurrent.strategy._
import java.util.concurrent.{ExecutorService, Executors}
case class ResultA(resultb: ResultB, resulta: ResultC)
case class ResultB()
case class ResultC()
run
def run {
implicit val executor: ExecutorService = Executors.newFixedThreadPool(8)
import Executor.strategy
val promiseA = doA
println("waiting for results")
val a: ResultA = promiseA.get
println("got " + a)
executor.shutdown
}
def doA(implicit s: Strategy[Unit]): Promise[ResultA] = {
println("triggered A")
val b = doB
val c = doC
for {bb <- b; cc <- c} yield ResultA(bb, cc)
}
def doB(implicit s: Strategy[Unit]): Promise[ResultB] = {
println("triggered B")
promise { Thread.sleep(1000); println("returning B"); ResultB() }
}
def doC(implicit s: Strategy[Unit]): Promise[ResultC] = {
println("triggered C")
promise { Thread.sleep(1000); println("returning C"); ResultC() }
}
}
输出:
triggered A
triggered B
triggered C
waiting for results
returning B
returning C
got ResultA(ResultB(),ResultC())
您将在Runar的Scalaz中找到presentation并发的简介。
这种方法不如Actors灵活,但组成更好,不会死锁。
答案 1 :(得分:7)
这是非常简化的,但展示了如何在三个演员之间拆分单个控制流,将状态传递给每个演员:
package blevins.example
import scala.continuations._
import scala.continuations.ControlContext._
import scala.actors.Actor._
import scala.actors._
object App extends Application {
val actorA, actorB, actorC = actor {
receive {
case f: Function1[Unit,Unit] => { f() }
}
}
def handle(a: Actor) = shift { k: (Unit=>Unit) =>
a ! k
}
// Control flow to split up
reset {
// this is not handled by any actor
var x = 1
println("a: " + x)
handle(actorA) // actorA handles the below
x += 4
println("b: " + x)
handle(actorB) // then, actorB handles the rest
var y = 2
x += 2
println("c: " + x)
handle(actorC) // and so on...
y += 1
println("d: " + x + ":" + y)
}
}
答案 2 :(得分:1)
请参阅Akka's Futures and how to compose them或scalaz's Promises,它们几乎相同,只是略有不同。