如何在 Scala 中取消 Future?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16009837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to cancel Future in Scala?
提问by Michael
Java Futurehas cancelmethod, which can interrupt the thread, which runs the Futuretask. For example, if I wrap an interruptibleblocking call in a Java FutureI can interrupt it later.
Java Future有cancel方法,可以中断运行Future任务的线程。例如,如果我将一个可中断的阻塞调用包装在 a 中,Java Future我可以稍后中断它。
Scala Futureprovides no cancelmethod. Suppose I wrap an interruptibleblocking call in a Scala Future. How can I interrupt it?
Scala Future没有提供任何cancel方法。假设我将一个可中断的阻塞调用包装在Scala Future. 我怎么能打断它?
采纳答案by axel22
This is not yet a part of the Futures API, but may be added as an extension in the future.
这还不是Futures API的一部分,但将来可能会作为扩展添加。
As a workaround, you could use the firstCompletedOfto wrap 2 futures - the future you want to cancel and a future that comes from a custom Promise. You could then cancel the thus created future by failing the promise:
作为一种解决方法,您可以使用firstCompletedOf来包装 2 个期货 - 您要取消的未来和来自自定义Promise. 然后,您可以通过未能兑现承诺来取消由此创建的未来:
def cancellable[T](f: Future[T])(customCode: => Unit): (() => Unit, Future[T]) = {
val p = Promise[T]
val first = Future firstCompletedOf Seq(p.future, f)
val cancellation: () => Unit = {
() =>
first onFailure { case e => customCode}
p failure new Exception
}
(cancellation, first)
}
Now you can call this on any future to obtain a "cancellable wrapper". Example use-case:
现在你可以在任何未来调用它来获得一个“可取消的包装器”。示例用例:
val f = callReturningAFuture()
val (cancel, f1) = cancellable(f) {
cancelTheCallReturningAFuture()
}
// somewhere else in code
if (condition) cancel() else println(Await.result(f1))
EDIT:
编辑:
For a detailed discussion on cancellation, see Chapter 4 in the Learning concurrent programming in Scalabook.
有关取消的详细讨论,请参阅《在 Scala 中学习并发编程》一书中的第 4 章。
回答by nightingale
I haven't tested this, but this expands on the answer of Pablo Francisco Pérez Hidalgo. Instead of blocking waiting for the java Future, we use an intermediate Promiseinstead.
我没有测试过这个,但这扩展了 Pablo Francisco Pérez Hidalgo 的答案。Future我们没有阻塞等待 java ,而是使用中间体Promise。
import java.util.concurrent.{Callable, FutureTask}
import scala.concurrent.{ExecutionContext, Promise}
import scala.util.Try
class Cancellable[T](executionContext: ExecutionContext, todo: => T) {
private val promise = Promise[T]()
def future = promise.future
private val jf: FutureTask[T] = new FutureTask[T](
new Callable[T] {
override def call(): T = todo
}
) {
override def done() = promise.complete(Try(get()))
}
def cancel(): Unit = jf.cancel(true)
executionContext.execute(jf)
}
object Cancellable {
def apply[T](todo: => T)(implicit executionContext: ExecutionContext): Cancellable[T] =
new Cancellable[T](executionContext, todo)
}
回答by George Pligoropoulos
By cancelling I guess you would like to violently interrupt the future.
通过取消,我猜您想猛烈地中断future.
Found this segment of code: https://gist.github.com/viktorklang/5409467
找到这段代码:https: //gist.github.com/viktorklang/5409467
Did a few tests and seems to work fine!
做了一些测试,似乎工作正常!
Enjoy :)
享受 :)
回答by Pablo Francisco Pérez Hidalgo
I think it is possible to reduce the complexity of the implementations provided by making use of the Java 7 Futureinterfaceand its implementations.
我认为可以通过使用Java 7Future接口及其实现来降低提供的实现的复杂性。
Cancellablecan build a Java future which is the one to be cancelled by its cancelmethod. Another future can wait for its completion thus becoming the observable interface which is itself immutable in state:
Cancellable可以构建一个 Java 未来,这是一个被其cancel方法取消的未来。另一个 Future 可以等待它的完成,从而成为 observable 接口,它本身的状态是不可变的:
class Cancellable[T](executionContext: ExecutionContext, todo: => T) {
private val jf: FutureTask[T] = new FutureTask[T](
new Callable[T] {
override def call(): T = todo
}
)
executionContext.execute(jf)
implicit val _: ExecutionContext = executionContext
val future: Future[T] = Future {
jf.get
}
def cancel(): Unit = jf.cancel(true)
}
object Cancellable {
def apply[T](todo: => T)(implicit executionContext: ExecutionContext): Cancellable[T] =
new Cancellable[T](executionContext, todo)
}

