【问题标题】:Tail Recurson without Await没有等待的尾递归
【发布时间】:2020-04-02 17:13:37
【问题描述】:

我有一个场景,当我在 map 中扭曲对 calltoFutureMethod(data) 方法的调用时,程序在未来调用执行之前结束。

所以我用 Await.result 替换了它,但我不想使用 Await,因为它会阻塞但也不能这样做:

calltoFutureMethod(data) map{
result => sendData(newData)
}

因为尾递归不允许这样做。没有尾递归的 Await 和 Thred.sleep 还有其他方法吗?

   @scala.annotation.tailrec
      def sendData(
      data: List[String]
      ): Unit =
    data match {
    case head::tail =>
         val result = for {
         p <- calltoFutureMethod(data)
         } yield p
         val putDataList = Await.result(result, 10.seconds)
         sendData(newData)
         }
    case Nil => ...
    }

    def callToFutureMethod(data: List[String]) =
    {
    Future
     {
     }
    }

【问题讨论】:

    标签: scala tail-recursion


    【解决方案1】:

    如果您在Future/IO/Task 或任何其他将蹦床实现为堆栈安全的结构上,则不需要使用尾递归。所以:

    calltoFutureMethod(data) map {
      result => sendData(newData)
    }
    

    安全。

    您的程序终止的事实可能是因为您使用的ExecutionContexta daemon(例如ExecutionContext.Implicits.global) - 如果所有剩余线程都是守护进程,则允许JVM终止,所以要么等待未来的结束在您的main 函数中,或定义/使用不是守护进程的ExecutionContext,至少对于这些期货而言。

    import java.util.concurrent.Executors
    
    import scala.concurrent.ExecutionContext
    
    // pick up whatever Executor you need
    implicit val customExecutionContext: ExecutionContext =
      ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
    

    【讨论】:

    • 效果很好。谢谢,但现在即使未来也完成了,它使程序保持活力。完成所有操作后有什么方法可以关闭应用程序吗?
    • 是的,一旦你结束你的程序并且你知道它应该结束 - 通过executor.shutdown()手动终止Executor(为此你需要在通过之前保存对Executor的引用它进入ExecutionContext)。
    猜你喜欢
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2021-08-28
    • 2020-08-11
    • 2016-02-21
    • 2016-03-21
    • 2017-06-22
    相关资源
    最近更新 更多