处理不可变类中的超时问题

7
我希望为一个长时间运行的任务创建一个线程安全(不可变)的Scala类。对于某些边缘情况,任务可能需要很长时间,因此我想实现一个超时机制。如何在不可变类中实现最佳超时机制?
我的第一次尝试是使用隐式参数,如下所示:
class Worker(val input: String) {

  def start: String = {
    implicit val startTimeStamp = new TimeStamp
    doSomething1 + doSomething2
  }

  def doSomething1()(implicit startTimeStamp: TimeStamp): String = { ... }

  def doSomething2()(implicit startTimeStamp: TimeStamp): String = {
    ... 
    checkTimeout 
    ...
   }
}

class TimeStamp { val start = System.currentTimeMillis }

这个应该可以工作,但是仍然有很多带有隐式参数的样板代码。(在真正的代码中,我有数百个嵌套在工作类中的 doSomething 函数。)在Scala中是否有更优美的方式来实现呢?

2个回答

5

听起来你正在寻找未来。在scala 2.9.x中,我建议你使用akka库来实现,从2.10.0开始有scala.concurrent.Future trait。

2.10的示例:

import concurrent._
import concurrent.duration._
import ExecutionContext.Implicits.global

val f = future {
  blocking {
    // long running task
  }
}

try {
  val res = Await.result(f, 100 millis)
} catch {
  case e: java.util.concurrent.TimeoutException =>
    // handle timeout
}

编辑:根据Viktor Klang的建议,添加了blocking调用。


只是一条注释:自2.10.0版本以来,Akka已成为Scala的一部分。 - xhudik
1
在Scala 2.9.1-2.9.2中,Futures和Promises被回溯到2.9.3版本。 - om-nom-nom
2
如果您正在未来执行长时间运行的操作,则应将其包装在“阻塞”调用中,以便底层ExecutionContext至少得到通知,该线程将被占用一段时间:http://www.scala-lang.org/api/current/index.html#scala.concurrent.package - Viktor Klang

3
使用 Hystrix。它是一个Java库,可以完全满足您的要求。与Scala兼容,并且有很棒的文档。
示例:
class LongOperation(...) extends HystrixCommand[Result](
  HystrixCommandProperties.Setter()
    .withExecutionIsolationThreadTimeoutInMilliseconds(60 * 1000))
{
  override protected def run: Result = {
    // your code
  }
}

如何同步执行:

val result = new LongOperation(...).execute()

谢谢,我不知道有这个有趣的Hystrix框架 :-o。对于像我这样的初学者来说,一些部分看起来与Akka相似。但我认为在Scala世界中,Akka解决方案更受欢迎,所以我采纳了drexin的答案。 - Sonson123
2
withExecutionIsolationThreadTimeoutInMilliseconds... 我有点讨厌Java。 - Dylan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接