java中Future的使用

Future是java 1.5引入的一个interface,可以方便的用于异步结果的获取。 本文将会通过具体的例子讲解如何使用Future。

创建Future

正如上面所说,Future代表的是异步执行的结果,意思是当异步执行结束之后,返回的结果将会保存在Future中。

那么我们什么时候会用到Future呢? 一般来说,当我们执行一个长时间运行的任务时,使用Future就可以让我们暂时去处理其他的任务,等长任务执行完毕再返回其结果。

经常会使用到Future的场景有:1. 计算密集场景。2. 处理大数据量。3. 远程方法调用等。

接下来我们将会使用ExecutorService来创建一个Future。

    <T> Future<T> submit(Callable<T> task);

上面是ExecutorService中定义的一个submit方法,它接收一个Callable参数,并返回一个Future。

我们用一个线程来计算一个平方运算:

    private ExecutorService executor
= Executors.newSingleThreadExecutor(); public Future<Integer> calculate(Integer input) {
return executor.submit(() -> {
System.out.println("Calculating..."+ input);
Thread.sleep(1000);
return input * input;
});
}

submit需要接受一个Callable参数,Callable需要实现一个call方法,并返回结果。这里我们使用lamaba表达式来简化这一个流程。

从Future获取结果

上面我们创建好了Future,接下来我们看一下怎么获取到Future的值。

       FutureUsage futureUsage=new FutureUsage();
Future<Integer> futureOne = futureUsage.calculate(20);
while(!futureOne.isDone()) {
System.out.println("Calculating...");
Thread.sleep(300);
}
Integer result = futureOne.get();

首先我们通过Future.isDone() 来判断这个异步操作是否执行完毕,如果完毕我们就可以直接调用futureOne.get()来获得Futre的结果。

这里futureOne.get()是一个阻塞操作,会一直等待异步执行完毕才返回结果。

如果我们不想等待,future提供了一个带时间的方法:

Integer result = futureOne.get(500, TimeUnit.MILLISECONDS);

如果在等待时间结束的时候,Future还有返回,则会抛出一个TimeoutException。

取消Future

如果我们提交了一个异步程序,但是想取消它, 则可以这样:

uture<Integer> futureTwo = futureUsage.calculate(4);

        boolean canceled = futureTwo.cancel(true);

Future.cancel(boolean) 传入一个boolean参数,来选择是否中断正在运行的task。

如果我们cancel之后,再次调用get()方法,则会抛出CancellationException。

多线程环境中运行

如果有两个计算任务,先看下在单线程下运行的结果。

        Future<Integer> future1 = futureUsage.calculate(10);
Future<Integer> future2 = futureUsage.calculate(100); while (!(future1.isDone() && future2.isDone())) {
System.out.println(
String.format(
"future1 is %s and future2 is %s",
future1.isDone() ? "done" : "not done",
future2.isDone() ? "done" : "not done"
)
);
Thread.sleep(300);
} Integer result1 = future1.get();
Integer result2 = future2.get(); System.out.println(result1 + " and " + result2);

因为我们通过Executors.newSingleThreadExecutor()来创建的单线程池。所以运行结果如下:

Calculating...10
future1 is not done and future2 is not done
future1 is not done and future2 is not done
future1 is not done and future2 is not done
future1 is not done and future2 is not done
Calculating...100
future1 is done and future2 is not done
future1 is done and future2 is not done
future1 is done and future2 is not done
100 and 10000

如果我们使用Executors.newFixedThreadPool(2)来创建一个多线程池,则可以得到如下的结果:

calculating...10
calculating...100
future1 is not done and future2 is not done
future1 is not done and future2 is not done
future1 is not done and future2 is not done
future1 is not done and future2 is not done
100 and 10000

本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/future

更多教程请参考 flydean的博客

java中Future的使用的更多相关文章

  1. java中Future与FutureTask使用与分析

    Future与FutureTask都是用于获取线程执行的返回结果.下面我们就对两者之间的关系与使用进行一个大致的介绍与分析 一.Future与FutureTask介绍: Future位于java.ut ...

  2. 【JAVA】java中Future、FutureTask的使用

    如今的系统基本都是分布式的,各个系统各司其职的,不可能一个系统干了全部系统的事. 所以系统之间的交互就越来越多了.那么系统之间的交互仅仅有通过网络来交互了,而网络必定会存在延时的情况. 比方A系统的一 ...

  3. C#的Task和Java的Future

    C#的Task和Java的Future 自从项目中语言换成Java后就很久没有看C#了,但说实话我是身在曹营心在汉啊.早就知道.NET4.5新增了async和await但一直没有用过,今天看到这篇文章 ...

  4. Java 多线程 - Future

    Java中Future的使用场景和解析 https://blog.csdn.net/hongtaolong/article/details/83349705 (细看!!!)

  5. 14.Java中的Future模式

    jdk1.7.0_79  本文实际上是对上文<13.ThreadPoolExecutor线程池之submit方法>的一个延续或者一个补充.在上文中提到的submit方法里出现了Future ...

  6. Java中的Future相关

    先上一个场景:假如你突然想做饭,但是没有厨具,也没有食材.网上购买厨具比较方便,食材去超市买更放心. 实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材.所以,在主线程里面另起一个子线 ...

  7. java中 immutable,future,nio

    什么是Future? 用过Java并发包的朋友或许对Future (interface) 已经比较熟悉了,其实Future 本身是一种被广泛运用的并发设计模式,可在很大程度上简化需要数据流同步的并发应 ...

  8. Java中的Runnable、Callable、Future、FutureTask的区别与示例

    Java中存在Runnable.Callable.Future.FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别. ...

  9. 关于Java中进程和线程的详解

    一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...

随机推荐

  1. Codeforces Round #627 (Div. 3)

    1324A - Yet Another Tetris Problem(思维) 题意 给一个数组,每一个数组中的元素大小表示在竖直方向的方块数量,元素相邻怎竖直方向的方块也相邻,类似于俄罗斯方块当底层被 ...

  2. My背包九讲——概述

    文章目录 什么是背包问题 背包问题的分类 [第一讲 01背包问题](https://blog.csdn.net/qq_34261446/article/details/103705068) 第二讲 完 ...

  3. hello world: 我的博客写作思路

    1. 本人计算机专业,研究生刚毕业,即将入职金融科技领域,决定借博客园平台写自己的博客,原因如下: 从小白到大白,离不开各大学习平台和技术博客的指导和分享,是时候回馈了. 借此机会整理自己从本科.研究 ...

  4. Java线程通讯方法之wait()、nofity() 详解

    Java线程通讯方法之wait().nofity() 详解 本文将探讨以下问题: synchronized 代码块使用 notify()与notifyAll()的区别 Java wait(),noti ...

  5. 基于 mpvue 框架的小程序选择控件,支持单列,多列,联动

    最近在学着写mpvue小程序,在做选择控件时候遇到了点问题,按照微信小程序方法picker,很不方便! 在网上搜到一个很好用的组件下面给大家分享: 组件说明文档链接:https://go.ctolib ...

  6. Struts2-学习笔记系列(13)-类型转换异常和校验器

    Struts2框架有默认的类型转换错误拦截机制,该配置在struts-default.xml中,名叫conversionError,但是想使用需要继承ActionSupport. 默认的错误提示信息是 ...

  7. hive常用函数二

    逻辑运算: 1. 逻辑与操作: AND 语法: A AND B 操作类型:boolean 说明:如果A和B均为TRUE,则为TRUE:否则为FALSE.如果A为NULL或B为NULL,则为NULL 举 ...

  8. GPS定位模块返回数据的处理

    本项目采用的是微科的VK2828U7G5LF,根据NMEA0183协议,打算采用反馈GPGLL语句来进行数据的处理. 1. 首先,本GPS模块默认的波特率是9600,因此,我们仅需要设置打开GPGLL ...

  9. Python队列的三种队列方法

    今天讲一下队列,用到一个python自带的库,queue 队列的三种方法有: 1.FIFO先入先出队列(Queue) 2.LIFO后入先出队列(LifoQueue) 3.优先级队列(PriorityQ ...

  10. Spring 下,关于动态数据源的事务问题的探讨

    开心一刻 毒蛇和蟒蛇在讨论谁的捕猎方式最高效. 毒蛇:我只需要咬对方一口,一段时间内它就会逐渐丧失行动能力,最后死亡. 蟒蛇冷笑:那还得等生效时间,我只需要缠住对方,就能立刻致它于死地. 毒蛇大怒:你 ...