我为Scala的期货编写了许多不同的单元测试。 所有异步调用都使用执行上下文。 为了确保异步调用始终以相同的顺序执行,我需要延迟一些非常困难的任务,这会使测试变慢。 执行者可能仍然(取决于其实现)先于其他任务完成。
以特定执行顺序测试并发代码的最佳方法是什么?例如,我有以下测试案例:
"firstSucc" should "complete the final future with the first one" in {
val executor = getExecutor
val util = getUtil
val f0 = util.async(executor, () => 10)
f0.sync
val f1 = util.async(executor, () => { delay(); 11 })
val f = f0.firstSucc(f1)
f.get should be(10)
}
其中延迟为def delay() = Thread.sleep(4000)
,而sync
则使将来同步(呼叫Await.ready(future, Duration.Inf)
)。
这就是我要确保f0已经完成并且f1在f0之后完成的方式。仅凭firstSucc
可能会使期货改组,因此仅完成f0是不够的。因此,应该将f1延迟到检查f.get
之后。
另一个想法是从承诺中创建期货并在特定的时间点完成它们:
"firstSucc" should "complete the final future with the first one" in {
val executor = getExecutor
val util = getUtil
val f0 = util.async(executor, () => 10)
val p = getPromise
val f1 = p.future
val f = f0.firstSucc(f1)
f.get should be(10)
p.trySuccess(11)
}
是否有更容易/更好的方法来定义执行顺序?也许是另一种执行服务,可以在其中配置已提交任务的顺序? 对于这种特定情况,将第二个期货推迟到检查结果之后可能就足够了,但是在某些情况下,必须按一定顺序完成所有期货。
完整的代码可以在这里找到:https://github.com/tdauth/scala-futures-promises
由于Scala可以使用Java Executor服务,所以此问题可能相关:Controlling Task execution order with ExecutorService
答案 0 :(得分:0)
对于大多数简单情况,我想说一个线程执行器就足够了-如果您一个接一个地执行期货,它们将被串行执行,并以相同的顺序完成。
但是看来您的问题实际上比您要描述的要复杂:您不仅在寻找一种方法来确保一个将来的完成时间晚于另一个,而且总的来说,一系列任意事件以特定顺序发生。例如,您问题中的摘录,即验证第一个完成之后的第二个开始(我不知道delay
的含义是顺便说一句)。
您可以使用eventually
等待特定事件发生,然后继续:
val f = Future(doSomething)
eventually {
someFlag shouldBe true
}
val f1 = Future(doSomethingElse)
eventually {
f.isCompleted shouldBe true
}
someFlag = false
eventually {
someFlag shouldBe true
}
f1.futureValue shoudlBe false