首页 > 解决方案 > 如何通过超时取消链接的 Scala 未来?

问题描述

假设我的未来定义如下所示:

import scala.concurrent.Future

def appendCharWithTimeout(transformationId: String, char: Char, delayTimeMs: Long, delayTimes: Int) = (s: String) => {
  for (i <- 1 to delayTimes) {
    println(s"$transformationId waiting iteration $i ...")
    Thread.sleep(delayTimeMs)
  }
  s"$s$char"
}

Future("Hello ")
  .map( appendCharWithTimeout("mapJ", 'J', 200, 5) )
  .map( appendCharWithTimeout("mapO", 'o', 200, 5) )
  .map( appendCharWithTimeout("mapH", 'h', 200, 5) )
  .map( appendCharWithTimeout("mapN", 'n', 200, 5) )
  .map( appendCharWithTimeout("map!", '!', 200, 5) )

这个future的执行时间是5秒(5 * 5 * 200ms)。

我正在寻找一种将这个未来包装在某种“超时上下文”中并通过超时停止执行的方法,因此不会执行所有转换。

理想情况下,我设想有这样的东西:

Future("Hello ")
  .within(2 seconds)
  .map( appendCharWithTimeout("mapJ", 'J', 200, 5) )
  .map( appendCharWithTimeout("mapO", 'o', 200, 5) )
  .map( appendCharWithTimeout("mapH", 'h', 200, 5) )
  .map( appendCharWithTimeout("mapN", 'n', 200, 5) )
  .map( appendCharWithTimeout("map!", '!', 200, 5) )

输出应该是:

mapJ waiting iteration 1 ...
mapJ waiting iteration 2 ...
mapJ waiting iteration 3 ...
mapJ waiting iteration 4 ...
mapJ waiting iteration 5 ...
mapO waiting iteration 1 ...
mapO waiting iteration 2 ...
mapO waiting iteration 3 ...
mapO waiting iteration 4 ...
mapO waiting iteration 5 ...

标签: scalafunctional-programmingtimeoutconcurrent.futures

解决方案


以下是执行此操作的几种方法:

0)不要链接Futures。执行是顺序的,因此只需在单个循环中使用循环Future并跟踪循环中的总经过时间。

1)在val外部记录开始时间,Future并使用它来修改给定的超时值,appendCharWithTimeout以便不超过总执行时间。

2)appendCharWithTimeout花费总执行时间并将剩余时间返回到下一次迭代。超过超时时使用它来停止执行。

选择取决于实际代码的实际作用,以及您是否可以更改appendCharWithTimeout.


推荐阅读