在Scala工作表中打印Futures的结果

 UIUI张南南 发布于 2023-02-07 17:18

我正在参加Coursera的Reactive编程课程,当我做其中一项任务时,我遇到了一些奇怪的东西.无论如何,我通过这个扩展为Future Companion对象添加了一些方法

implicit class FutureCompanionOps[T](val f: Future.type) extends AnyVal {

    /** Returns a future that is always completed with `value`.
     */
    def always[T](value: T): Future[T] = Future(value)

    /** Returns a future that is never completed.
     *
     *  This future may be useful when testing if timeout logic works correctly.
     */
    def never[T]: Future[T] = Promise().future


    /** Given a list of futures `fs`, returns the future holding the list of values of all the futures from `fs`.
     *  The returned future is completed only once all of the futures in `fs` have been completed.
     *  The values in the list are in the same order as corresponding futures `fs`.
     *  If any of the futures `fs` fails, the resulting future also fails.
     */
    def all[T](fs: List[Future[T]]): Future[List[T]] = {
      val resPr = Promise[List[T]]()
      def function( in: List[Future[T]], fxs:Future[List[T]] ): Future[List[T]] =
      {
        if(in.isEmpty) fxs 
        else
        function( in.tail, for { i <- in.head ; xs <- fxs } yield { i :: xs } ) 
      }
      function( fs, resPr.success(Nil).future )
    }
}

然后我在Eclipse中的Scala WorkSheet上写了这个

object TestSheet {

val tempPr = Promise[Boolean]()      
val anotherFuLs = List( Future.always(true), Future.always(false), tempPr.future )
                                                  //> anotherFuLs  : List[scala.concurrent.Future[Boolean]] = List(scala.concurren
                                                  //| t.impl.Promise$DefaultPromise@a19b1de, scala.concurrent.impl.Promise$Default
                                                  //| Promise@1cec6b00, scala.concurrent.impl.Promise$DefaultPromise@625dcec6)
  val crapFut = Future.all(anotherFuLs)           //> crapFut  : scala.concurrent.Future[List[Boolean]] = scala.concurrent.impl.Pr
                                                  //| omise$DefaultPromise@6564dbd5
  crapFut.isCompleted                             //> res3: Boolean = false
  tempPr.success(false)                           //> res4: nodescala.TestSheet.tempPr.type = scala.concurrent.impl.Promise$Defaul
                                                  //| tPromise@625dcec6
  crapFut.isCompleted                             //> res5: Boolean = true
  crapFut onComplete {
    case Success(ls) => println( ls )
    case Failure(e) => println( "Failed with Exception " + e )
  }
} 

无论我怎么做都不能让Scala工作表打印出结果列表的值.但是,当我编写单元测试并运行scala测试时,我在比较最终结果列表时没有问题.在使用异步内容时,这是scala工作表中的错误吗?

这是单元测试

test("A composed future with all should complete when all futures complete") {
    val tempPr = Promise[Boolean]()
    val lsFu = List( Future.always(true), Future.always(false), tempPr.future );
    val fuL = Future.all( lsFu )
    fuL onComplete { case Success(ls) => println( "This got done" ); assert( ls === List( true, false, true ), "I should get back the expected List" ) 
                     case Failure(ex) => assert( false, "Failed with Exception " + ex ) } 
    assert( fuL.isCompleted === false, "The resulting Future should not be complete when the depending futures are still pending" )    
    tempPr.success(true)

  }

Dylan.. 8

看起来问题是运行工作表代码的主线程在onComplete处理程序运行之前结束.

Scala的默认ExecutionContext值实际上是一个充满守护程序线程的线程池.在此上下文中的"守护进程"意味着即使该线程忙于执行某些操作,也不会阻止JVM在所有非守护程序线程完成时关闭.在您的情况下,主线程可能是程序中唯一的非守护程序线程.

调用onCompleteFuture将使得隐式提供的ExecutionContext将在Future完成时执行您的处理程序.这意味着处理程序在守护程序线程上运行.因为这onComplete是你在main方法中做的最后一件事,所以JVM只是在ExecutionContext运行处理程序之前完成.

通常情况下,这不是什么大问题.在像Web服务器这样的场景中,您的JVM将启动并运行很长时间.对于您的用例,我建议使用其中一种方法阻止Future完成scala.concurrent.Await.这样,您可以在main方法中将完成逻辑作为主线程的一部分运行.

1 个回答
  • 看起来问题是运行工作表代码的主线程在onComplete处理程序运行之前结束.

    Scala的默认ExecutionContext值实际上是一个充满守护程序线程的线程池.在此上下文中的"守护进程"意味着即使该线程忙于执行某些操作,也不会阻止JVM在所有非守护程序线程完成时关闭.在您的情况下,主线程可能是程序中唯一的非守护程序线程.

    调用onCompleteFuture将使得隐式提供的ExecutionContext将在Future完成时执行您的处理程序.这意味着处理程序在守护程序线程上运行.因为这onComplete是你在main方法中做的最后一件事,所以JVM只是在ExecutionContext运行处理程序之前完成.

    通常情况下,这不是什么大问题.在像Web服务器这样的场景中,您的JVM将启动并运行很长时间.对于您的用例,我建议使用其中一种方法阻止Future完成scala.concurrent.Await.这样,您可以在main方法中将完成逻辑作为主线程的一部分运行.

    2023-02-07 17:20 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有