最近在开发中使用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)
}

Scala之Future超时的更多相关文章

  1. scala(二) Future执行逻辑解读

    在scala中是没有原生线程的,其底层使用的是java的Thread机制.但是在scala中对java Thread进行了封装,实现了更便于操作线程的Future. 官方文档: Futures pro ...

  2. scala akka Future 顺序执行 sequential execution

    对于 A => B => C 这种 future 之间的操作,akka 默认会自动的按照顺序执行,但对于数据库操作来说,我们希望几个操作顺序执行,就需要使用语法来声明 有两种声明 futu ...

  3. Scala之Future

    一.简介 Future提供了一套高效便捷的非阻塞并行操作管理方案.其基本思想很简单,所谓Future,指的是一类占位符对象,用于指代某些尚未完成的计算的结果.一般来说,由Future指代的计算都是并行 ...

  4. ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用!因此,ES transport client可以同步调用也可以异步(不过底层的socket必然是异步实现)

    ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用! 因此,ES tra ...

  5. netty底层是事件驱动的异步库 但是可以await或者sync(本质是future超时机制)同步返回 但是官方 Prefer addListener(GenericFutureListener) to await()

    io.netty.channel 摘自:https://netty.io/4.0/api/io/netty/channel/ChannelFuture.html Interface ChannelFu ...

  6. Akka系列(五):Java和Scala中的Future

    前言....... 随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue ...

  7. SDP(13): Scala.Future - far from completion,绝不能用来做甩手掌柜

    在前面几篇关于数据库引擎的讨论里很多的运算函数都返回了scala.Future类型的结果,因为我以为这样就可以很方便的实现了non-blocking效果.无论任何复杂的数据处理操作,只要把它们包在一个 ...

  8. 混合使用ForkJoin+Actor+Future实现一千万个不重复整数的排序(Scala示例)

    目标       实现一千万个不重复整数的排序,可以一次性加载到 2G 的内存里. 本文适合于想要了解新语言 Scala 并发异步编程框架 Akka, Future 的筒鞋. 读完本文后,将了解如何综 ...

  9. Scala教程之:Future和Promise

    文章目录 定义返回Future的方法 阻塞方式获取Future的值 非阻塞方式获取Future的值 Future链 flatmap VS map Future.sequence() VS Future ...

随机推荐

  1. BZOJ 1531: [POI2005]Bank notes

    按余数分类 单调队列优化 #include<cstdio> using namespace std; int n,m,b[205],c[205],F[20005]; struct node ...

  2. python如何合并两个字典

    我有两个Python字典,如何合并它们呢?update()方法正是你所需要的. >>> x = {'a':1, 'b': 2} >>> y = {'b':10, ' ...

  3. border,border-width不支持百分比

    1.border-width不支持百分比 原因:不会因为设备大就按比例变大 同样的,outline,box-shadow,text-shadow也不支持百分比 也就是border不支持百分比 2.bo ...

  4. laravel5.2总结--任务调度

    你可以通过 command() 来调用 artisan 命令, call 来调用方法或函数, 或者 terminal() 来执行单行命令脚本:   1.在app/Console/Commands文件夹 ...

  5. Leetcode 636.函数的独占时间

    函数的独占时间 给出一个非抢占单线程CPU的 n 个函数运行日志,找到函数的独占时间. 每个函数都有一个唯一的 Id,从 0 到 n-1,函数可能会递归调用或者被其他函数调用. 日志是具有以下格式的字 ...

  6. vlc无法播放.flv视频文件

    解决方法:https://videoconverter.wondershare.com/vlc/flv-not-displaying-video-vlc-media-player.html. 在pre ...

  7. Mysql实战之索引

    author:JevonWei 版权声明:原创作品 索引基础: 索引:提取索引的创建在的表上字段中的数据,构建出一个独特的数据结构: 索引的作用:加速查询操作:副作用:降低写操作性能: 表中数据子集: ...

  8. FreeBSD利用 ports 來安裝軟體

    FreeBSD利用 ports 來安裝軟體   利用 ports 來安裝軟體 FreeBSD 的 ports 就是別人已經編譯過,安裝測試沒問題了,他們將軟體編譯時所需的組態設定.編譯程序及安裝程序, ...

  9. LoadRunner中请求HTTPS页面。

    哎,真是服了.国内网站上写的解决方法如此的粗糙. 如果用loadrunner访问HTTPS网页时出现:shut connection during attempt to negotiate SSL s ...

  10. pat 甲级 1066. Root of AVL Tree (25)

    1066. Root of AVL Tree (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue An A ...