Akka / Scala:将Future与pipeTo映射到

时间:2017-12-11 05:39:24

标签: scala akka actor

Akka个actor中,在通过以下方式将Future结果发送给另一个actor之间的线程数或线程锁定方面是否有任何差异:

一个。将Future映射到tell结果到actor的函数。

B中。定义关于未来的onSuccess回调,其中tell结果为演员。

℃。使用FuturepipeTo结果传递给参与者。

上一个问题讨论了其中一些选项:

Akka: Send a future message to an Actor

三者中哪一个是首选方式,为什么?

此外,我想知道,如果receive的类型为Any => Unit,那么为什么代码会编译情况receive的部分功能会返回Future,而不是Unit

以下是我在上面提到的三个选项的代码示例:

import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.pattern.ask
import akka.util.Timeout
import akka.pattern.pipe

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.util.Success

class ActorIncrement extends Actor {

  def receive = {
    case i: Int =>
      println(s"increment $i")
      sender ! i + 1
  }
}

class ActorEven extends Actor {

  def receive = {
    case i: Int =>
      println(s"$i is even")
  }
}


class ActorOdd extends Actor {

  def receive = {
    case i: Int =>
      println(s"$i is odd")
  }
}

class MyActor(actorIncrement: ActorRef, actorEven: ActorRef, actorOdd: ActorRef) extends Actor {
  import scala.concurrent.ExecutionContext.Implicits.global

  implicit val timeout = Timeout(5 seconds)

  def receive = {
    case i: Int if i % 2 == 0 =>
      println(s"receive a: $i")
      actorIncrement ? i map {
        case j: Int =>
          println(s"$j from increment a")
          actorOdd ! j
      }
    case i: Int =>
      println(s"receive b: $i")
      val future: Future[Any] = actorIncrement ? i
      future onSuccess {
        case i: Int =>
          println(s"$i from increment b")
          actorEven ! i
      }

    case s: String =>
      println(s"receive c: $s")
      (actorIncrement ? s.toInt).mapTo[Int] filter(_ % 2 == 0) andThen { case Success(i: Int) => println(s"$i from increment c") } pipeTo actorEven
  }
}

object TalkToActor extends App {

  // Create the 'talk-to-actor' actor system
  val system = ActorSystem("talk-to-actor")

  val actorIncrement = system.actorOf(Props[ActorIncrement], "actorIncrement")
  val actorEven = system.actorOf(Props[ActorEven], "actorEven")
  val actorOdd = system.actorOf(Props[ActorOdd], "actorOdd")

  val myActor = system.actorOf(Props(new MyActor(actorIncrement, actorEven, actorOdd)), "myActor")

  myActor ! 2
  myActor ! 7
  myActor ! "11"

  Thread.sleep(1000)

  //shutdown system
  system.terminate()
}

1 个答案:

答案 0 :(得分:11)

如果您查看pipeTo中<{1}}的定义方式,

akka.pattern.PipeToSupport

正如您所看到的那样...... def pipeTo(recipient: ActorRef)(implicit sender: ActorRef = Actor.noSender): Future[T] = { future andThen { case Success(r) ⇒ recipient ! r case Failure(f) ⇒ recipient ! Status.Failure(f) } } } 与仅向pipeTo添加andThen调用无关,而Future会将未来结果或Status.Failure消息发送至如果您Future失败,则为管道演员。

现在主要区别在于Status.Failure故障处理。如果您没有使用pipeTo,您可以以任何您想要的方式处理您的失败。