zoukankan      html  css  js  c++  java
  • Scala之Future超时

    最近在开发中使用akka http进行请求,返回的是一个future,并且要对future进行超时设置,不知怎么设置,因此学习了下。

    一、Future阻塞

    首先,scala中的future不支持内置超时,要想达到这样的目的,可以使用Await进行阻塞,具体例子如下:

    import scala.concurrent._
    import scala.concurrent.duration._
    import ExecutionContext.Implicits.global

    lazy val f = future { Thread.sleep(2000); true }
    Await.result(f, 1 second)

    上面的代码将超时,报如下错误:

    java.util.concurrent.TimeoutException:
        at scala.concurrent.impl.Promise $ DefaultPromise.ready(Promise.scala:219)
        at scala.concurrent.impl.Promise $ DefaultPromise.result(Promise.scala:223)
        at scala.concurrent.Await $$ anonfun $ result $ 1.apply(package.scala:107)
        at scala.concurrent.BlockContext $ DefaultBlockContext $ .blockOn(BlockContext.scala:53) 
    ...

    二、非阻塞Future超时

    但是,我们知道,在future上设置阻塞不是官网推荐的一种方式,因为这会浪费一个线程。因此,我们可以使用akka after实现一种非阻塞式的future超时:

    import scala.concurrent._
    import scala.concurrent.duration._
    import ExecutionContext.Implicits.global
    import scala.util.{Failure, Success}
    import akka.actor.ActorSystem
    import akka.pattern.after

    val system = ActorSystem("theSystem")

    lazy val f = future { Thread.sleep(2000); true }
    lazy val t = after(duration = 1 second, using = system.scheduler)(Future.failed(new TimeoutException("Future timed out!")))

    val fWithTimeout = Future firstCompletedOf Seq(f, t)

    fWithTimeout.onComplete {
    case Success(x) => println(x)
    case Failure(error) => println(error)
    }

    但是,注意了,为了确保在执行前,计时还没有开始,必须将after设置lazy val。

    但是上述这种模式的缺点是它依赖于akka,因此,我们可以使用纯scala模式,来模仿实现after的功能

    为了更容易使用future的超时设置,我们可以使用隐式类来扩展scala future从而支持超时:

    import scala.concurrent._
    import scala.concurrent.duration.FiniteDuration
    import ExecutionContext.Implicits.global
    import akka.actor.ActorSystem
    import akka.pattern.after

    implicit class FutureExtensions[T](f: Future[T]) {
    def withTimeout(timeout: => Throwable)(implicit duration: FiniteDuration, system: ActorSystem): Future[T] = {
    Future firstCompletedOf Seq(f, after(duration, system.scheduler)(Future.failed(timeout)))
    }
    }

    现在,我们可以随时很方便的给future设置超时了:

    import scala.concurrent._
    import scala.concurrent.duration._
    import scala.util.{ Success, Failure }
    import ExecutionContext.Implicits.global
    import akka.actor.ActorSystem

    implicit val system = ActorSystem("theSystem")
    implicit val timeout = 1 second

    lazy val f = future { Thread.sleep(2000); true }

    f withTimeout new TimeoutException("Future timed out!") onComplete {
    case Success(x) => println(x)
    case Failure(error) => println(error)
    }
  • 相关阅读:
    竞赛入门经典 3.2竖式问题
    竞赛入门经典 3-4竖式
    hdu 3547 (polya定理 + 小高精)
    浅入 dancing links x(舞蹈链算法)
    计算阶乘的另一些有趣的算法(转载)
    莫比乌斯反演
    STL的常用用法、函数汇总(不定时更新)
    博弈论的总结
    14年安徽省赛数论题etc.
    CCF 第六次计算机职业认证 第四题 收货 stl动态存储和fleury算法的综合应用
  • 原文地址:https://www.cnblogs.com/junjiang3/p/9695426.html
Copyright © 2011-2022 走看看