Cancellation with Future and Promise in Scala

后端 未结 4 1391
情歌与酒
情歌与酒 2020-12-06 02:02

This is a followup to my previous question.

Suppose I have a task, which executes an interruptible blocking call. I would like to run it as a Future<

4条回答
  •  春和景丽
    2020-12-06 02:51

    Here is the interruptable version of Victor's code per his comments (Victor, please correct me if I misinterpreted).

    object CancellableFuture extends App {
    
      def interruptableFuture[T](fun: () => T)(implicit ex: ExecutionContext): (Future[T], () => Boolean) = {
        val p = Promise[T]()
        val f = p.future
        val aref = new AtomicReference[Thread](null)
        p tryCompleteWith Future {
          val thread = Thread.currentThread
          aref.synchronized { aref.set(thread) }
          try fun() finally {
            val wasInterrupted = (aref.synchronized { aref getAndSet null }) ne thread
            //Deal with interrupted flag of this thread in desired
          }
        }
    
        (f, () => {
          aref.synchronized { Option(aref getAndSet null) foreach { _.interrupt() } }
          p.tryFailure(new CancellationException)
        })
      }
    
      val (f, cancel) = interruptableFuture[Int] { () =>
        val latch = new CountDownLatch(1)
    
        latch.await(5, TimeUnit.SECONDS)    // Blocks for 5 sec, is interruptable
        println("latch timed out")
    
        42  // Completed
      }
    
      f.onFailure { case ex => println(ex.getClass) }
      f.onSuccess { case i => println(i) }
    
      Thread.sleep(6000)   // Set to less than 5000 to cancel
    
      val wasCancelled = cancel()
    
      println("wasCancelled: " + wasCancelled)
    }
    

    With Thread.sleep(6000) the output is:

    latch timed out
    42
    wasCancelled: false
    

    With Thread.sleep(1000) the output is:

    wasCancelled: true
    class java.util.concurrent.CancellationException
    

提交回复
热议问题