【问题标题】:How can I safely do retries on a Scala Future?如何安全地重试 Scala Future?
【发布时间】:2016-02-25 10:07:56
【问题描述】:

我有一些启动“慢”过程的代码,我将其包装在 Future 中。如果出现问题,我想在暂停后慢慢循环并重试——无限期。有点像这样:(我知道最终会有人干预并解决问题)

  def doSomething():Unit = {
    aFutureThing().onComplete { 
      case Success(s) => println("Success: "+s)
      case Failure(x) =>
        // Take some (hopefully) corrective action here, call for help, etc.
        Thread.sleep(1000) // pause a bit
        doSomething() // and try again...
    }
  }
  doit()

当调用 onComplete 回调时,doSomething() 是否仍在堆栈上,还是因为我们在 Future 执行慢速任务 (aFutureThing) 时返回而将其弹出? doSomething 的递归调用(最终)会炸毁堆栈/OutOfMemory 吗?如果是这样......有没有更安全的方法来重试未来?

【问题讨论】:

  • 作为(重要的)旁注:您绝对应该在生产代码中的未来内部调用Thread.sleep,因为这将阻塞未来当前正在执行的线程上。相反,您应该安排另一个未来在以后执行。例如,请参阅其他问题:stackoverflow.com/questions/16359849/scala-scheduledfuture

标签: scala future


【解决方案1】:

这里没有递归。 doSomething 将创建 Future 并立即返回,而 Future 被提交以在另一个线程上执行(如果它是池的一部分,它实际上可能在同一个线程上执行,但不是在 doSomething 返回之前.

您可以通过在 repl 中运行类似的内容来亲自看到这一点:

def foo(n: Int): Future[Int] = Future {
   Thread.sleep(1000)
   if(n < 10) throw new IllegalArgumentException(); else n 
} recoverWith { case e => 
   e.printStackTrace();
   println("N was " + n)
   Thread.sleep(1000)
   println("Rinse and repeat!")
   foo(n+1)
}

foo(1)

它会“重试”9次才真正成功,并且每次都打印异常的堆栈,所以你可以看到回溯是相同的,它们不会增长,因为没有递归。

【讨论】:

    猜你喜欢
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 2013-04-07
    • 2023-03-17
    • 1970-01-01
    • 2021-01-18
    相关资源
    最近更新 更多