如何取消未来在Scala呢?(How to cancel Future in Scala?)

2019-08-31 05:45发布

Java的未来已经cancel方法,它可以中断线程,运行于Future任务。 例如,如果我换一个中断阻塞调用在Java Future我以后可以中断它。

斯卡拉未来没有提供cancel方法。 假设我包裹在一个中断阻塞调用Scala Future 。 我怎样才能打断呢?

Answer 1:

这还不是一部分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中学习并发编程的书。



Answer 2:

我没有测试过这一点,但它扩展了巴勃罗·佩雷斯旧金山伊达尔戈的答案。 而不是阻塞等待了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)
}


Answer 3:

通过取消我猜你想用暴力中断future

发现这个段的代码: https://gist.github.com/viktorklang/5409467

做了一些测试,似乎好工作!

请享用 :)



Answer 4:

我认为这是可能减少通过利用所提供的实施方案的复杂性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)
 }


文章来源: How to cancel Future in Scala?