Scala 如何从一系列期货中仅读取成功的价值

Scala 如何从一系列期货中仅读取成功的价值,scala,akka,future,Scala,Akka,Future,我正在学习akka/scala,我试图只阅读那些从Seq[Future[Int]]中成功的Futures,但无法获得任何工作 我模拟了一个由10个Future[Int]组成的数组,根据FailThreshold所取的值,其中一些数组会失败(10个都会失败,0个都不会失败) 然后,我尝试将它们读入ArrayBuffer(无法找到返回带值的不可变结构的方法) 此外,对于成功/失败没有筛选,因此必须在以后的每个时间运行onComplete,并作为副作用更新缓冲区 即使当FailThreshold=0且

我正在学习akka/scala,我试图只阅读那些从
Seq[Future[Int]]
中成功的
Future
s,但无法获得任何工作

  • 我模拟了一个由10个
    Future[Int]
    组成的数组,根据
    FailThreshold
    所取的值,其中一些数组会失败(10个都会失败,0个都不会失败)
  • 然后,我尝试将它们读入ArrayBuffer(无法找到返回带值的不可变结构的方法)
  • 此外,对于成功/失败没有筛选,因此必须在以后的每个时间运行
    onComplete
    ,并作为副作用更新缓冲区
  • 即使当
    FailThreshold=0
    且Seq已将all Future设置为Success时,数组缓冲区有时为空,不同的运行返回不同大小的数组
  • 我在网上尝试了一些其他的建议,比如在列表中使用
    Future.sequence
    ,但是如果未来的变量失败,就会抛出异常

    
    输入akka.actor_
    导入akka.pattern.ask
    导入scala.concurrent.{wait,Future,Promise}
    导入scala.concurrent.duration_
    导入scala.util.{超时,失败,成功}
    导入concurrent.ExecutionContext.Implicits.global
    case对象asknamessage
    隐式val超时=超时(5秒)
    val FailThreshold=0
    类HeyActor(num:Int)扩展了Actor{
    def接收={
    case asknamessage=>if(num{
    println(t)
    val b=scala.collection.mutable.ArrayBuffer.empty[Int]
    t、 foldLeft(b){案例(bf,ft)=>
    ft.onComplete{case Success(v)=>bf+=ft.value.get.get}
    高炉
    }
    println(b)
    }
    }
    }
    val系统=ActorSystem(“AskTest”)
    val flm=(0到10).map((n)=>system.actorOf(Props(new HeyActor(n)),name=“futureListMake”+(n)))
    val flp=system.actorOf(Props(新FLPActor),name=“futureListProcessor”)
    //val delay=akka.pattern.after(500毫秒,使用=system.scheduler)(Future.failed(抛出新的IllegalArgumentException(“完成”))
    val delay=akka.pattern.after(500毫秒,使用=system.scheduler)(Future.successful(0))
    val seqOfFtrs=(0到10).map((n)=>Future.firstCompletedOf(Seq(delay,flm(n)?asknamessage)).mapTo[Int])
    flp!seqOfFtrs
    
    FLPActor
    中的
    receive
    主要是

    Vector(Future(Success(0)), Future(Success(1)), Future(Success(2)), Future(Success(3)), Future(Success(4)), Future(Success(5)), Future(Success(6)), Future(Success(7)), Future(Success(8)), Future(Success(9)), Future(Success(10)))
    
    但是数组缓冲区
    b
    的值数量不同,有时为空

    有人能给我指一下这里的空隙吗

    • 为什么阵列缓冲区会有不同的大小,即使所有未来的解决方案都取得了成功
    • 当我们想
      ask
      不同的参与者超时并且只使用那些成功返回的ask进行进一步处理时,正确的模式是什么

    与直接发送IndexedSeq[Future[Int]]不同,您应该转换为Future[IndexedSeq[Int]],然后通过管道将其发送给下一个参与者。您不直接将期货发送给参与者。您必须通过管道将其发送

    HeyActor可以保持不变

    之后

    val seqOfFtrs = (0 to 10).map( (n) => Future.firstCompletedOf( Seq(delay, flm(n) ? AskNameMessage) ).mapTo[Int] )
    
    执行恢复,并使用Future.sequence将其转换为一个未来:

    val oneFut = Future.sequence(seqOfFtrs.map(f=>f.map(Some(_)).recover{ case (ex: Throwable) => None})).map(_.flatten)
    
    如果您不了解“部分”、“无”和“展平”的业务,请确保您了解选项类型。从序列中删除值的一种方法是将序列中的值映射到选项(部分或无),然后展平序列。将删除“无”值,并展开部分值

    将数据转换为单个未来后,将其传送到FLPActor:

    oneFut pipeTo flp
    
    应使用以下接收功能重写FLPActor:

    def receive = {
      case printme: IndexedSeq[Int] => println(printme)
    }
    
    在Akka中,从未来或未来的未完成修改参与者主线程中的某些状态是一个很大的禁忌。在最坏的情况下,这会导致竞争条件。请记住,每个未来都在其自己的线程上运行,因此在参与者内运行未来意味着您在不同的线程中同时进行工作。拥有未来指令当参与者也在处理某些状态时,不要修改参与者中的某些状态。某些状态会导致灾难。在Akka中,您直接在主参与者执行的主线程中处理对状态的所有更改。如果您将来有一些工作要做,并且需要从参与者的主线程访问这些工作,则将其传输到该参与者。pipeTo模式对于访问已完成的未来计算是功能性的、正确的和安全的

    要回答您关于为什么FLPActor没有正确打印IndexedSeq的问题:您正在打印ArrayBuffer,而您的期货尚未完成。在这种情况下,onComplete不是正确的习惯用法,您通常应该避免使用它,因为它不是好的功能样式


    不要忘记pipeTo语法的import akka.pattern.pipe。

    不要直接发送IndexedSeq[Future[Int]],你应该转换到Future[IndexedSeq[Int]],然后通过管道将其发送给下一个参与者。你不直接将未来发送给参与者。你必须通过管道将其发送

    HeyActor可以保持不变

    之后

    val seqOfFtrs = (0 to 10).map( (n) => Future.firstCompletedOf( Seq(delay, flm(n) ? AskNameMessage) ).mapTo[Int] )
    
    执行恢复,并使用Future.sequence将其转换为一个未来:

    val oneFut = Future.sequence(seqOfFtrs.map(f=>f.map(Some(_)).recover{ case (ex: Throwable) => None})).map(_.flatten)
    
    如果您不了解“部分”、“无”和“展平”的业务,请确保您了解选项类型。从序列中删除值的一种方法是将序列中的值映射到选项(部分或无),然后展平序列。将删除“无”值,并展开部分值

    将数据转换为单个未来后,将其传送到FLPActor:

    oneFut pipeTo flp
    
    应使用以下接收功能重写FLPActor:

    def receive = {
      case printme: IndexedSeq[Int] => println(printme)
    }
    
    在Akka中,从未来或未来的未完成修改参与者主线程中的某些状态是一个很大的禁忌。在最坏的情况下,这会导致竞争条件。请记住,每个未来都在其自己的线程上运行,因此在参与者内运行未来意味着您在不同的线程中同时进行工作。拥有未来指令巧妙地修改