Kill or timeout a Future in Scala 2.10

前端 未结 3 1896
失恋的感觉
失恋的感觉 2021-01-04 20:11

Hi,

I\'m using Scala 2.10 with the new futures library and I\'m trying to write some code to test an infinite loop. I use a scala.concurrent.Future to r

相关标签:
3条回答
  • 2021-01-04 20:16

    Do not try it at home.

    import scala.concurrent._
    import scala.concurrent.duration._
    
    class MyCustomExecutionContext extends AnyRef with ExecutionContext {
      import ExecutionContext.Implicits.global
      @volatile var lastThread: Option[Thread] = None
      override def execute(runnable: Runnable): Unit = {
        ExecutionContext.Implicits.global.execute(new Runnable() {
          override def run() {
            lastThread = Some(Thread.currentThread)
            runnable.run()
          }
        })
      }
      override def reportFailure(t: Throwable): Unit = ???
    }    
    
    implicit val exec = new MyCustomExecutionContext()
    val f = future[Int]{ do{}while(true); 1 }
    try {
      Await.result(f, 10 seconds) // 100% cpu here
    } catch {
      case e: TimeoutException => 
        println("Stopping...")
        exec.lastThread.getOrElse(throw new RuntimeException("Not started"))
          .stop() // 0% cpu here
    }
    
    0 讨论(0)
  • 2021-01-04 20:19

    No - you will have to add a flag that your loop checks. If the flag is set, stop the loop. Make sure the flag is at least volatile.

    See Java Concurrency in Practice, p 135-137.

    0 讨论(0)
  • 2021-01-04 20:19

    I had a similar problem and wrote the following nonblocking future op:

    class TerminationToken(var isTerminated: Boolean)
    object TerminationToken { def apply() = new TerminationToken(false) }
    
     implicit class FutureOps[T](future: Future[Option[T]]) {
     def terminate(timeout: FiniteDuration, token: TerminationToken): Future[Option[T]] = {
       val timeoutFuture = after[Option[T]](timeout, using = context.system.scheduler) {
         Future[Option[T]] { token.isTerminated = true; None } }
              Future.firstCompletedOf[Option[T]](Seq (future recover { case _ => None }, timeoutFuture))
         }
       }
    

    Then just create a future that returns an option, and use .terminate(timeout, token) on it

    0 讨论(0)
提交回复
热议问题