简体   繁体   English

在Scala 2.10中杀死或超时未来

[英]Kill or timeout a Future in Scala 2.10

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. 我正在使用Scala 2.10和新的期货库,我正在尝试编写一些代码来测试无限循环。 I use a scala.concurrent.Future to run the code with the loop in a separate thread. 我使用scala.concurrent.Future在一个单独的线程中使用循环运行代码。 I would then like to wait a little while to do some testing and then kill off the separate thread/future. 然后我想等一会儿做一些测试,然后杀死单独的线程/未来。 I have looked at Await.result but that doesn't actually kill the future. 我看过Await.result但实际上并没有杀死未来。 Is there any way to timeout or kill the new Scala 2.10 futures? 有没有办法超时或杀死新的Scala 2.10期货?

I would prefer not having to add external dependencies such as Akka just for this simple part. 我宁愿不必为这个简单的部分添加外部依赖项,如Akka。

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
}

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 . 确保标志至少是volatile

See Java Concurrency in Practice , p 135-137. 请参阅实践中的Java Concurrency ,第135-137页。

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 然后创建一个返回选项的future,并在其上使用.terminate(timeout,token)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM