所以,我在stackoverflow上看到一些关于以某种方式询问如何“杀死”未来的问题,而不是弃用的Thread.stop()。我看到答案解释了为什么不可能,但没有解决类似问题的替代机制。
例如:Practical use of futures? Ie, how to kill them?
我意识到未来不能被“杀死”。
我知道如何以Java方式执行此操作:将任务分解为较小的睡眠,并在定期检查的线程类中具有一些“volatile boolean isStillRunning”。如果我通过更新此值取消了该线程,则该线程退出。这涉及“共享状态”(isStillRunning var),如果我在Scala中做同样的事情,它似乎不会非常“有用”。
在惯用功能标量中解决此类问题的正确方法是什么?有一个相当简洁的方法吗?我应该恢复“正常”线程和易失性标志吗?我应该以与Java关键字相同的方式使用@volatile吗?
答案 0 :(得分:1)
是的,它看起来和Java一样。
对于测试装置,测试可能会挂起或运行时间过长,我会使用承诺来测试失败(出于任何原因)。例如,超时监视器可以“取消”测试运行器(中断线程并比较并设置一个标志),然后完成失败的承诺。或者测试准备可能会导致配置错误的测试失败。或者,测试运行并产生结果。在更高的层次上,测试台只能看到未来及其价值。
与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
})
答案 1 :(得分:1)
我想我已经找到了解决自己问题的更好方法。我可以向actor发送更高优先级的退出消息,而不是使用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布尔值。