Cómo cancelar Future in Scala?

Java Future tiene un método de cancel , que puede interrumpir el hilo, que ejecuta la tarea Future . Por ejemplo, si cierro una llamada de locking interrumpible en Java Future , puedo interrumpirla más tarde.

Scala Future no proporciona ningún método de cancel . Supongamos que envuelvo una llamada de locking interrumpible en un Scala Future . ¿Cómo puedo interrumpirlo?

Esto aún no forma parte de la API de Future , pero puede agregarse como una extensión en el futuro.

Como solución alternativa, puede usar el firstCompletedOf para ajustar 2 futuros: el futuro que desea cancelar y un futuro que proviene de una Promise personalizada. A continuación, puede cancelar el futuro así creado fallando la promesa:

 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) } 

Ahora puede llamar esto en cualquier futuro para obtener un “contenedor cancelable”. Ejemplo de uso-caso:

 val f = callReturningAFuture() val (cancel, f1) = cancellable(f) { cancelTheCallReturningAFuture() } // somewhere else in code if (condition) cancel() else println(Await.result(f1)) 

EDITAR:

Para una discusión detallada sobre la cancelación, vea el Capítulo 4 en la progtwigción concurrente de Aprendizaje en el libro de Scala .

No lo he probado, pero esto se amplía a la respuesta de Pablo Francisco Pérez Hidalgo. En lugar de bloquear la espera del Future java, utilizamos una Promise intermedia en su lugar.

 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) } 

Al cancelar, supongo que te gustaría interrumpir violentamente el future .

Encontrado este segmento de código: https://gist.github.com/viktorklang/5409467

¡Hizo algunas pruebas y parece funcionar bien!

Disfruta 🙂

Creo que es posible reducir la complejidad de las implementaciones proporcionadas al hacer uso de la interfaz Java 7 Future y sus implementaciones.

Cancellable puede construir un futuro Java que será cancelado por su método cancel . Otro futuro puede esperar hasta que se complete convirtiéndose en la interfaz observable que es inmutable en su estado:

  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) } 
    Intereting Posts