你好,
我将 Scala 2.10 与新的期货库一起使用,我正在尝试编写一些代码来测试无限循环。我使用 ascala.concurrent.Future
在单独的线程中运行带有循环的代码。然后我想等一会儿做一些测试,然后杀死单独的线程/未来。我看过,Await.result
但这实际上并没有扼杀未来。有什么方法可以超时或终止新的 Scala 2.10 期货?
我宁愿不必为这个简单的部分添加诸如 Akka 之类的外部依赖项。
你好,
我将 Scala 2.10 与新的期货库一起使用,我正在尝试编写一些代码来测试无限循环。我使用 ascala.concurrent.Future
在单独的线程中运行带有循环的代码。然后我想等一会儿做一些测试,然后杀死单独的线程/未来。我看过,Await.result
但这实际上并没有扼杀未来。有什么方法可以超时或终止新的 Scala 2.10 期货?
我宁愿不必为这个简单的部分添加诸如 Akka 之类的外部依赖项。
不要在家里尝试。
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
}
否 - 您必须添加一个循环检查的标志。如果设置了标志,则停止循环。确保标志至少为volatile
.
请参阅Java 并发实践,第 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