【发布时间】:2019-06-20 15:58:44
【问题描述】:
我是 Scala 的新手,我正在通过创建一些重试方案来练习 Futures 库。这样做我得到了以下代码:
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object Retries extends App {
var retries = 0
def resetRetries(): Unit = retries = 0
def calc() = if (retries > 3) 10 else {
retries += 1
println(s"I am thread ${Thread.currentThread().getId} This is going to fail. Retry count $retries")
throw new IllegalArgumentException("This failed")
}
def fCalc(): Future[Int] = Future(calc())
resetRetries()
val ff = fCalc() // 0 - should fail
.fallbackTo(fCalc()) // 1 - should fail
.fallbackTo(fCalc()) // 2 - should fail
.fallbackTo(fCalc()) // 3 - should fail
.fallbackTo(fCalc()) // 4 - should be a success
Await.ready(ff, 10.second)
println(ff.isCompleted)
println(ff.value)
}
每次我运行这段代码都会得到不同的结果。我得到的结果示例如下
输出 1
I am thread 12 This is going to fail. Retry count 1
I am thread 14 This is going to fail. Retry count 3
I am thread 13 This is going to fail. Retry count 2
I am thread 11 This is going to fail. Retry count 1
I am thread 12 This is going to fail. Retry count 4
true
Some(Failure(java.lang.IllegalArgumentException: This failed))
输出 2
I am thread 12 This is going to fail. Retry count 2
I am thread 11 This is going to fail. Retry count 1
I am thread 13 This is going to fail. Retry count 3
I am thread 14 This is going to fail. Retry count 4
true
Some(Success(10))
输出 3
I am thread 12 This is going to fail. Retry count 1
I am thread 11 This is going to fail. Retry count 1
I am thread 12 This is going to fail. Retry count 2
I am thread 12 This is going to fail. Retry count 3
I am thread 12 This is going to fail. Retry count 4
true
Some(Failure(java.lang.IllegalArgumentException: This failed))
结果并非总是在成功和失败之间交替出现。可能会出现多次失败的运行,直到出现成功的运行。
据我了解,“我是线程 x 这将失败。重试计数 x”的日志应该只有 4 条,这些应该如下:
I am thread a This is going to fail. Retry count 1
I am thread b This is going to fail. Retry count 2
I am thread c This is going to fail. Retry count 3
I am thread d This is going to fail. Retry count 4
不一定按这个顺序——因为我不知道 Scala 线程模型是如何工作的——但你明白我的意思。尽管如此,我得到了我无法处理的不确定性输出。所以...... 我的问题是:这种不确定的输出来自哪里?
我想提一下,以下重试机制始终会产生相同的结果:
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object Retries extends App {
var retries = 0
def resetRetries(): Unit = retries = 0
def calc() = if (retries > 3) 10 else {
retries += 1
println(s"I am thread ${Thread.currentThread().getId} This is going to fail. Retry count $retries")
throw new IllegalArgumentException("This failed")
}
def retry[T](op: => T)(retries: Int): Future[T] = Future(op) recoverWith { case _ if retries > 0 => retry(op)(retries - 1) }
resetRetries()
val retriableFuture: Future[Future[Int]] = retry(calc())(5)
Await.ready(retriableFuture, 10 second)
println(retriableFuture.isCompleted)
println(retriableFuture.value)
}
输出
I am thread 11 This is going to fail. Retry count 1
I am thread 12 This is going to fail. Retry count 2
I am thread 11 This is going to fail. Retry count 3
I am thread 12 This is going to fail. Retry count 4
true
Some(Success(10))
如果我减少重试次数 (retry(calc())(3)),结果是预期的失败未来
I am thread 11 This is going to fail. Retry count 1
I am thread 12 This is going to fail. Retry count 2
I am thread 11 This is going to fail. Retry count 3
I am thread 12 This is going to fail. Retry count 4
true
Some(Failure(java.lang.IllegalArgumentException: This failed))
【问题讨论】: