当前位置:首页 > 科技  > 软件

三分钟带你搞懂 Future 玩法

来源: 责编: 时间:2024-01-16 10:17:03 357观看
导读一、摘要在前几篇线程系列文章中,我们介绍了线程池的相关技术,任务执行类只需要实现Runnable接口,然后交给线程池,就可以轻松的实现异步执行多个任务的目标,提升程序的执行效率,比如如下异步执行任务下载。// 创建一个线程
一、摘要

在前几篇线程系列文章中,我们介绍了线程池的相关技术,任务执行类只需要实现Runnable接口,然后交给线程池,就可以轻松的实现异步执行多个任务的目标,提升程序的执行效率,比如如下异步执行任务下载。b0Z28资讯网——每日最新资讯28at.com

// 创建一个线程池ExecutorService executor = Executors.newFixedThreadPool(2);// 提交任务executor.submit(new Runnable() {    @Override    public void run() {        // 执行下载某文件任务        System.out.println("执行下载某文件任务");    }});

而实际上Runnable接口并不能满足所有的需求,比如有些场景下,我们想要获取任务执行的返回结果,Runnable接口因为无返回值,只能想办法通过额外的方式来写入和读取,操作起来十分不便。b0Z28资讯网——每日最新资讯28at.com

因此,从 JDK 1.5 开始,Java 标准库提供了一个Callable接口,与Runnable接口相比,它的方法上多了一个返回值;同时Callable是一个泛型接口,可以返回指定类型的结果,比如如下的实现类!b0Z28资讯网——每日最新资讯28at.com

public class Task implements Callable<String> {    @Override    public String call() throws Exception {        // 执行下载某文件任务        System.out.println("执行下载某文件任务");        return "xxx";    }}

问题来了,如何获取异步执行的结果呢?b0Z28资讯网——每日最新资讯28at.com

在 JDK 1.5 中,Java 标准库还提供了一个Future接口,它可以用来获取异步执行的结果。b0Z28资讯网——每日最新资讯28at.com

下面我们一起来了解一下这个Future接口!b0Z28资讯网——每日最新资讯28at.com

二、Future

Future接口,表示一个可能还没有完成异步任务的结果,它提供了检查任务是否已完成、以及等待任务完成并获取结果等方法。b0Z28资讯网——每日最新资讯28at.com

如果看过ExecutorService.submit()方法,会发现它的返回参数都是Future类型,Future类型的实例可以用来获取异步任务执行的结果。b0Z28资讯网——每日最新资讯28at.com

下面我们先来看一个简单的示例,以便于更好的理解!b0Z28资讯网——每日最新资讯28at.com

public class Task implements Callable<String> {        @Override    public String call() throws Exception {        // 执行下载某文件任务,并返回文件名称        System.out.println("thread name:" +  Thread.currentThread().getName() + " 开始执行下载任务");        return "xxx.png";    }}
public class FutureTest {    public static void main(String[] args) throws Exception {        // 创建一个线程池        ExecutorService executor = Executors.newFixedThreadPool(1);        // 初始化一个任务        Callable<String> task = new Task();        // 提交任务并获得Future的实例        Future<String> future = executor.submit(task);        // 从Future获取异步执行返回的结果(可能会阻塞等待结果)        String result =future.get();        System.out.println("任务执行结果:" +  result);        // 任务执行完毕之后,关闭线程池(可选)        executor.shutdown();    }}

输出结果如下:b0Z28资讯网——每日最新资讯28at.com

thread name:pool-1-thread-1 开始执行下载任务任务执行结果:xxx.png

从以上的示例可以清晰的看到,当需要获取异步线程的执行结果返回值时,通常需要搭配使用Future和Callable接口来实现,大体可以用如下步骤来概括:b0Z28资讯网——每日最新资讯28at.com

  • 首先提交一个实现Callable接口的任务到线程池中
  • 然后获取一个Future类型的对象
  • 最后在主线程中调用Future对象的get()方法,如果异步任务执行完成,就可以直接获得结果;如果异步任务执行没有完成,get()方法会阻塞,直到任务执行完成后才能获取结果

分析源码你会发现,Callable接口主要用途是定义一个支持返回结果的方法;重点实现主要集中在Future接口上。b0Z28资讯网——每日最新资讯28at.com

下面我们重点来看下Future接口方法!b0Z28资讯网——每日最新资讯28at.com

2.1、Future 接口方法

方法
b0Z28资讯网——每日最新资讯28at.com

描述
b0Z28资讯网——每日最新资讯28at.com

get()b0Z28资讯网——每日最新资讯28at.com

获取结果(会阻塞等待)
b0Z28资讯网——每日最新资讯28at.com

get(long timeout, TimeUnit unit)b0Z28资讯网——每日最新资讯28at.com

在指定的时间内获取结果,如果超时,会抛异常并退出等待状态
b0Z28资讯网——每日最新资讯28at.com

cancel(boolean mayInterruptIfRunning)b0Z28资讯网——每日最新资讯28at.com

尝试取消当前任务,当传入参数为true时,表示尝试中断任务的执行,false表示不中断,继续执行直到完成,如果取消成功,返回true;反之falseb0Z28资讯网——每日最新资讯28at.com

isCancelled()b0Z28资讯网——每日最新资讯28at.com

判断任务是否已取消
b0Z28资讯网——每日最新资讯28at.com

isDone()b0Z28资讯网——每日最新资讯28at.com

判断任务是否已完成
b0Z28资讯网——每日最新资讯28at.com

2.2、Future 接口实现类

Future本质其实是一个接口,并不是具体的实现类,真正负责工作的还是它的实现类来完成。b0Z28资讯网——每日最新资讯28at.com

我们还是以上文的线程池ExecutorService.submit()方法为例,看看它用的是哪种实现类!b0Z28资讯网——每日最新资讯28at.com

分析一下源码,会发现线程池用的实现类是FutureTask,关键核心源码如下:b0Z28资讯网——每日最新资讯28at.com

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {    return new FutureTask<T>(callable);}

FutureTask类是一个实现了Future接口所有功能的具体类,可直接使用它来实现获取异步任务执行的结果值。b0Z28资讯网——每日最新资讯28at.com

FutureTask的工作原理其实也并不复杂,它接受一个Callable或者Runnable对象作为参数,然后在线程池执行器中执行该任务,最后通过get()方法可以同步等待获取任务的执行结果。b0Z28资讯网——每日最新资讯28at.com

真正起到关键作用的是,在FutureTask内部,封装了一个状态变量,用于记录任务的状态(等待、运行、完成、取消等),以及任务执行结果或异常信息,通过该状态变量,我们可以判断任务是否已完成、以及获取任务的执行结果等信息。b0Z28资讯网——每日最新资讯28at.com

因为FutureTask也实现了Runnable接口,因此我们也可以将FutureTask作为任务,提交给线程池执行器。b0Z28资讯网——每日最新资讯28at.com

具体示例如下:b0Z28资讯网——每日最新资讯28at.com

public class FutureTest {    public static void main(String[] args) throws Exception {        // 1.创建一个线程池        ExecutorService executor = Executors.newFixedThreadPool(1);        // 2.初始化一个任务        Callable<String> callable = new Task();        // 3.创建FutureTask对象        FutureTask<String> futureTask = new FutureTask<>(callable);        // 4.提交任务给执行器执行        executor.execute(futureTask);        // 5.获取任务的执行结果        String result = futureTask.get(3, TimeUnit.SECONDS);        System.out.println("任务执行结果:" +  result);        // 6.关闭线程池(可选)        executor.shutdown();    }}

输出结果同上!b0Z28资讯网——每日最新资讯28at.com

如果想尝试取消任务的执行,也可以通过如下方式来实现!b0Z28资讯网——每日最新资讯28at.com

boolean isSuccess = futureTask.cancel(true);System.out.println("任务是否取消成功:" +  isSuccess);

除此之外,如果仔细的分析Future接口的类关系,会发现它的实现类非常的多,FutureTask只是它的一个基础实现类而已,部分类关系图如下!b0Z28资讯网——每日最新资讯28at.com

图片图片b0Z28资讯网——每日最新资讯28at.com

其它常用实现类简介:b0Z28资讯网——每日最新资讯28at.com

  • CompletableFuture:支持传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法
  • ForkJoinTask:支持把一个大任务拆成多个小任务,然后并行执行,在多核 CPU 上可以显著提升程序的执行效率
  • ScheduledFuture:支持周期性定时的执行任务,其中ScheduledFutureTask是一个私有类,只能通过ScheduledThreadPoolExecutor初始化操作

关于CompletableFuture、ForkJoinTask和ScheduledFuture,我们会在后面的文章中,再次单独介绍具体的用法。b0Z28资讯网——每日最新资讯28at.com

三、小结

本文主要围绕Future接口用法做了一次简单的知识总结,其中FutureTask类是Future接口中一个非常重要的实现类,通过它可以获取异步任务执行的返回值,通常用于异步计算带有返回值的任务。b0Z28资讯网——每日最新资讯28at.com

限于篇幅的原因,本文没有对FutureTask做过深入的原理讲解,主要围绕具体用法进行介绍,有兴趣的朋友可以阅读这篇文章《Java的Future机制详解》,以便更清晰的了解它的实现原理。b0Z28资讯网——每日最新资讯28at.com

如果有描述不对的地方,欢迎留言指出,共同进步!b0Z28资讯网——每日最新资讯28at.com

四、参考

1.https://www.liaoxuefeng.com/wiki/1252599548343744/1306581155184674b0Z28资讯网——每日最新资讯28at.com

2.https://www.cnblogs.com/xrq730/p/4872722.htmlb0Z28资讯网——每日最新资讯28at.com

3.https://juejin.cn/post/7231074060787908663b0Z28资讯网——每日最新资讯28at.com

4.https://zhuanlan.zhihu.com/p/54459770b0Z28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-62362-0.html三分钟带你搞懂 Future 玩法

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: IT降本50%还贼稳!百万订单规模系统的技术治理实践

下一篇: Swift 可选类型、可选绑定和可选链

标签:
  • 热门焦点
  • 一加Ace2 Pro真机揭晓 钛空灰配色质感拉满

    终于,在经过了几波预热之后,一加Ace2 Pro的外观真机图在网上出现了。还是博主数码闲聊站曝光的,这次的外观设计还是延续了一加11的方案,只是细节上有了调整,例如新加入了钛空灰
  • 石头自清洁扫拖机器人G10S评测:多年黑科技集大成之作 懒人终极福音

    科技圈经常能看到一个词叫“缝合怪”,用来形容那些把好多功能或者外观结合在一起的产品,通常这样的词是贬义词,但如果真的是产品缝合的好、缝合的实用的话,那它就成了中性词,今
  • 三万字盘点 Spring 九大核心基础功能

    大家好,我是三友~~今天来跟大家聊一聊Spring的9大核心基础功能。话不多说,先上目录:图片友情提示,本文过长,建议收藏,嘿嘿嘿!一、资源管理资源管理是Spring的一个核心的基础功能,不
  • “又被陈思诚骗了”

    作者|张思齐 出品|众面(ID:ZhongMian_ZM)如今的国产悬疑电影,成了陈思诚的天下。最近大爆电影《消失的她》票房突破30亿断层夺魁暑期档,陈思诚再度风头无两。你可以说陈思诚的
  • 东方甄选单飞:有些鸟注定是关不住的

    文/彭宽鸿编辑/罗卿东方甄选创始人俞敏洪带队的&ldquo;7天甘肃行&rdquo;直播活动已在近日顺利收官。成立后一年多时间里,东方甄选要脱离抖音自立门户的传闻不绝于耳,&ldquo;7
  • 微博大门常打开,迎接海外画师漂洋东渡

    作者:互联网那些事&ldquo;起猛了,我能看得懂日语了&rdquo;。&ldquo;为什么日本人说话我能听懂?&rdquo;&ldquo;中文不像中文,日语不像日语,但是我竟然看懂了&rdquo;&hellip;&hell
  • 网传小米汽车开始筛选交付中心 建筑面积不低于3000平方米

    7月7日消息,近日有微博网友@长三角行健者爆料称,据经销商集团反馈,小米汽车目前已经开始了交付中心的筛选工作,要求候选场地至少有120个车位,建筑不能低
  • 质感不错!OPPO K11渲染图曝光:旗舰IMX890传感器首次下放

    一直以来,OPPO K系列机型都保持着较为均衡的产品体验,历来都是2K价位的明星机型,去年推出的OPPO K10和OPPO K10 Pro两款机型凭借各自的出色配置,堪称有
  • “买真退假” 这种“羊毛”不能薅

    □ 法治日报 记者 王春   □ 本报通讯员 胡佳丽  2020年初,还在上大学的小东加入了一个大学生兼职QQ群。群主&ldquo;七王&rdquo;在群里介绍一些刷单赚
Top