4

所以,我看到一些关于 stackoverflow 的问题以一种或另一种方式询问如何“杀死”未来,例如已弃用的 Thread.stop()。我看到答案解释了为什么这是不可能的,但不是解决类似问题的替代机制。

例如:期货的实际使用?即,如何杀死他们?

我意识到未来不能被“杀死”。

我知道如何用 Java 的方式做到这一点:将任务分解为更小的睡眠,并在定期检查的线程类中有一些“volatile boolean isStillRunning”。如果我通过更新此值取消了线程,则线程退出。这涉及“共享状态”(isStillRunning 变量),如果我在 Scala 中做同样的事情,它看起来就不是很“实用”。

在惯用的函数式scala中解决这类问题的正确方法是什么?有没有合理简洁的方法来做到这一点?我应该恢复到“正常”线程和 volatile 标志吗?我应该以与 Java 关键字相同的方式使用 @volatile 吗?

4

2 回答 2

1

是的,它看起来和 Java 中的一样。

对于测试台,测试可能会挂起或运行时间过长,我使用一个承诺来保证测试失败(无论出于何种原因)。例如,超时监视器可以“取消”测试运行程序(中断线程并 compareAndSet 一个标志),然后完成失败的承诺。或者测试准备可能会提前失败配置错误的测试。或者,测试运行并产生结果。在更高的层次上,测试台只是看到了未来及其价值。

与 Java 不同的是您可以选择组合期货。

val all = Future.traverse(tests)(test => {
  val toKeep = promise[Result]    // promise to keep, or fail by monitor
  val f = for (w <- feed(prepare(test, toKeep))) yield {
    monitored(w, toKeep) {
      listener.start(w)
      w.runTest()
    }
  }
  f completing consume _
  // strip context
  val g = f map (r => r.copy(context = null))
  (toKeep completeWith g).future
})
于 2012-09-06T09:13:07.523 回答
1

我想我已经找到了解决我自己问题的更好方法。我可以向参与者发送更高优先级的退出消息,而不是使用 volatile 变量让操作知道何时死亡。它看起来像这样:

val a = new Actor() { 
  def act():Unit = {
    loop{ react {
      case "Exit" => exit(); return;
      case MyMessage => {
        //this check makes "Exit" a high priority message, if "Exit" 
        //is on the queue, it will be handled before proceeding to 
        //handle the real message.
        receiveWithin(0) {
          case "Exit" => exit(); return
          case TIMEOUT => //don't do anything.
        }
        sender ! "hi!" //reply to sender
      }
    }}
  }
}

a.start()
val f = a !! MyMessage
while( ! f.isSet && a.getState != Actor.State.Terminated ) {
  //will probably return almost immediately unless the Actor was terminated
  //after I checked.
  Futures.awaitAll(100,f)
}
if( a.getState != Actor.State.Terminated ) {
  f() // the future should evaluate to "hi!"
}
a ! "Exit" //stops the actor from processing anymore messages.
           //regardless of if any are still on the queue.
a.getState // terminated

可能有一种更简洁的方法来编写这个..但这大约是我在我的应用程序中所做的。

reactWithin(0) 是立即无操作,除非队列上有“退出”消息。队列中的“退出”消息替换了我将在线程 Java 应用程序中放入的 volatile 布尔值。

于 2012-09-10T04:13:17.967 回答