多线程设计模式 - Future 模式之 JAVA 原生实现

本贴最后更新于 1698 天前,其中的信息可能已经东海扬尘

之前一篇文章中介绍了 Future 设计模式的设计思想以及具体实现,今天我们来讲一下使用 JDK 原生实现。

JDK 内置的 Future 设计模式主要使用到了 Callable 接口和 FutureTask 类。

Callable

Callable 是类似于 Runnable 的接口,实现 Callable 接口的类和实现 Runnable 的类都是可被其他线程执行的任务。Callable 接口的定义如下:

public interface Callable<V> {  
    /**  
     * Computes a result, or throws an exception if unable to do so.  
     *  
     * @return computed result  
     * @throws Exception if unable to compute a result  
     */  
    V call() throws Exception;  
}

Callable 的类型参数是返回值的类型。例如:

Callable<Integer> 表示一个最终返回 Integer 对象的异步计算。

FutureTask

在认识 FutureTask 之前我们先来了解一下保存计算结果的接口类 Future
在实际应用中可以启动一个计算,将 Future对象 交给某个线程,然后执行其他操作。Future 对象的所有者在结果计算好之后就可以获得它。Future 接口具有下面的方法:

public interface Future<V> { 
    boolean cancel(boolean mayInterruptIfRunning); 
    boolean isCancelled(); boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

第一个 get 方法的调用被阻塞,直到计算完成。
如果在计算完成之前,第二个 get 方法的调用超时,抛出一个 TimeoutException 异常。
如果运行该计算的线程被中断,两个方法都将抛出 InterruptedException
如果计算已经完成,那么 get 方法立即返回。如果计算还在进行,isDone 方法返回 false;如果完成了,则返回 true。

可以用 cancel 方法取消该计算。如果计算还没有开始,它被取消且不再开始。如果计算处于运行之中,那么如果 mayInterrupt 参数为 true,它就被中断。

认识了 Future 类后我们再来认识 FutureTask,FutureTask 包装器是一种非常便利的机制,同时实现了 FutureRunnable 接口。FutureTask 有 2 个构造方法:

public FutureTask(Callable<V> callable) { 
    if (callable == null) throw new NullPointerException(); 
    this.callable = callable; 
    this.state = NEW;       // ensure visibility of callable
 } 

public FutureTask(Runnable runnable, V result) { 
    this.callable = Executors.callable(runnable, result); 
    this.state = NEW;       // ensure visibility of callable
}

通常,我们会使用 Callable 示例构造一个 FutureTask 对象,并将它提交给线程池进行处理,下面我们将展示这个内置的 Future 模式的使用。

public class RealData implements Callable<String> { 
    private String param; 
    public RealData(String param){ 
        this.param = param;
    }
    @Override 
    public String call() throws Exception {
        StringBuffer sb = new StringBuffer(); 
        for(int i = 0 ; i< 10 ;i++){
            sb.append(param); try {
                Thread.sleep(100);
            }catch (InterruptedException e){
                
            }
        } 
        return sb.toString();
    }
}

上述代码实现了 Callable 接口,它的 Call 方法会构造我们需要的真实数据并返回,当然这个过程比较缓慢,这里使用 Thread.sleep()来模拟它:

public class FutureMain {
    public static void main(String[] args)
            throws ExecutionException, InterruptedException {
        //构造FutureTask
        FutureTask<String> futureTask = new FutureTask<String>(new RealData("xxx"));
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        //执行FutureTask,发送请求
        //在这里开启线程进行RealData的call()执行
        executorService.submit(futureTask);

        System.out.println("请求完毕。。。");
        try {
            //这里可以进行其他额外的操作,这里用sleep代替其他业务的处理
            Thread.sleep(200);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
        //获取call()方法的返回值
        //如果此时call()方法没有执行完成,则依然会等待
        System.out.println("真实数据:"+futureTask.get());
    }
}

上述代码就是使用 Future 模式的典型。构造 FutureTask 时使用实现 Callable 接口的实现类,告诉 FutureTask 我们需要的数据应该有返回值。然后将 FutureTask 提交给线程池,接下来我们不用关心数据是怎么产生的,可以去做其他的业务逻辑处理,然后在需要的时候调用 FutureTask.get() 得到实际的数据。

Future 模式在日常业务中处理复杂业务时会经常用到,希望大家都能掌握。

  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    198 引用 • 120 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 7 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 401 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 473 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    16 引用 • 7 回帖 • 2 关注
  • 旅游

    希望你我能在旅途中找到人生的下一站。

    86 引用 • 897 回帖 • 1 关注
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 160 关注
  • 996
    13 引用 • 200 回帖 • 5 关注
  • Gzip

    gzip (GNU zip)是 GNU 自由软件的文件压缩程序。我们在 Linux 中经常会用到后缀为 .gz 的文件,它们就是 Gzip 格式的。现今已经成为互联网上使用非常普遍的一种数据压缩格式,或者说一种文件格式。

    9 引用 • 12 回帖 • 125 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 194 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖 • 19 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 30 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    84 引用 • 139 回帖 • 1 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    85 引用 • 122 回帖 • 617 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 1 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    198 引用 • 120 回帖
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    5 引用 • 26 回帖 • 499 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    180 引用 • 400 回帖 • 1 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    186 引用 • 471 回帖 • 3 关注
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 52 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 458 关注
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖 • 1 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    62 引用 • 289 回帖
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 20 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    28 引用 • 66 回帖 • 7 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    21 引用 • 37 回帖 • 523 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    186 引用 • 318 回帖 • 329 关注