scala - 如何测试期货是否在Scala中按顺序运行?
问题描述
假设我有这个方法:
def callApis(f1, f2, f3):Future[Result] {
for {
a <- Future { f1 }
b <- Future { f2 }
c <- Future { f3 }
} yield Result(a,b,c)
}
如果您熟悉 scala,您会知道 for 块中的行将按顺序执行。更具体地说,将首先计算 a。然后当我们得到 a 的结果时,代码将计算 b。然后当我们得到 b 的结果时,代码将计算 c。
我的问题是,如何编写一个单元测试来确保始终在计算 b 之前计算 a,并且始终在计算 c 之前计算 b?我担心的是,如果有人对 scala 中的期货如何运作知之甚少。他们可能会意外地使此代码异步运行。
我的意思是人们可能会不小心做这样的事情,这使得 a,b,c 被异步计算(我不希望人们这样做):
def callApis(f1, f2, f3):Future[Result] {
val fut1 = Future { f1 }
val fut2 = Future { f2 }
val fut3 = Future { f3 }
for {
a <- fut1
b <- fut2
c <- fut3
} yield Result(a,b,c)
}
解决方案
也许尝试定义一个单线程执行上下文,并在应该串行执行的块中要求它。例如,
trait SerialExecutionContext extends ExecutionContext {
val singleThreadPool = Executors.newFixedThreadPool(1, (r: Runnable) => new Thread(r, s"single-thread-pool"))
val serialEc = ExecutionContext.fromExecutor(singleThreadPool)
override def execute(runnable: Runnable): Unit = serialEc.execute(runnable)
override def reportFailure(cause: Throwable): Unit = serialEc.reportFailure(cause)
}
def callApis()(implicit ec: SerialExecutionContext): Future[Result] = {
val fut1 = Future { ...doSomething... }
val fut2 = Future { ...doSomething... }
val fut3 = Future { ...doSomething... }
for {
a <- fut1
b <- fut2
c <- fut3
} yield Result(a,b,c)
}
现在callApis
只有当我们可以在编译时证明存在串行执行上下文时才能进行评估。由于在正文中我们只有一个可用线程,futures 只能在前一个线程完成后才强制启动。
推荐阅读
- php - PHP 联系表单提交错误
- java - 如何清除日历框中输入的默认值并发送新的出生日期
- javascript - 预览图片上传多个输入
- python - CNN 的多个输入:图像和参数,如何合并
- java - 将地图转换为列表
- 作为每个列表条目的“键值” - python - 如何从模板调用模型函数?
- java - Android 给出错误“无法在单个 dex 文件中容纳请求的类”
- mysql - 为什么学说 2 不支持 GROUP_CONCAT()、DATE_FORMAT()?
- c# - FSharp 函数/方法体作为脚本执行,但在运行时不作为源文件执行
- python - 为 Windows 安装 web3.py 时遇到问题