Java的未来已经cancel
方法,它可以中断线程,运行于Future
任务。 例如,如果我换一个中断阻塞调用在Java Future
我以后可以中断它。
斯卡拉未来没有提供cancel
方法。 假设我包裹在一个中断阻塞调用Scala Future
。 我怎样才能打断呢?
Java的未来已经cancel
方法,它可以中断线程,运行于Future
任务。 例如,如果我换一个中断阻塞调用在Java Future
我以后可以中断它。
斯卡拉未来没有提供cancel
方法。 假设我包裹在一个中断阻塞调用Scala Future
。 我怎样才能打断呢?
这还不是一部分Future
的API,但可以作为对未来的扩展。
作为一种变通方法,您可以使用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)
}
现在你可以把这种对未来获得“撤销包装”。 实施例用例:
val f = callReturningAFuture()
val (cancel, f1) = cancellable(f) {
cancelTheCallReturningAFuture()
}
// somewhere else in code
if (condition) cancel() else println(Await.result(f1))
编辑:
有关取消了详细的讨论,请参见第4章在Scala中学习并发编程的书。
我没有测试过这一点,但它扩展了巴勃罗·佩雷斯旧金山伊达尔戈的答案。 而不是阻塞等待了Java的Future
,我们使用了一个中间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)
}
通过取消我猜你想用暴力中断future
。
发现这个段的代码: https://gist.github.com/viktorklang/5409467
做了一些测试,似乎好工作!
请享用 :)
我认为这是可能减少通过利用所提供的实施方案的复杂性Java 7的Future
接口和它的实现。
Cancellable
可以建立一个Java的未来这是由它的被取消的cancel
方法。 另一种未来可以等待这样它的完成成为观察到的接口,它本身是不变的状态:
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)
}