一. Future模式介绍

前面的 Thread-Per-Message 模式将耗时时间的处理交给其他线程, 的确可以提高程序的响应性, 但是在将处理交出去的时候, 处理结果仍是未知的, 而等待处理结果的话, 线程的响应性就会降低, 这时就可以使用 Future 模式

假设我们去蛋糕店买蛋糕, 下单时, 店员一遍递给我们提货单, 一边说 "请你傍晚再来取蛋糕", 到了傍晚, 我们就可以拿着提货单去取蛋糕, Futrue 就是未来的意思, 假设有一个方法需要花费很长时间才能获取到运行结果, 那么, 与其一直等待结果, 不如先拿一张 "提货单", 获取提货单并不耗费时间, 这里的 "提货单" 我们就称为 Future 角色     

获取 Future 角色的线程会在稍后使用 Future 角色来获取运行结果, 这与凭借着提货单去取蛋糕非常相似, 如果运行结果已经出来了, 那么直接领取就可以, 如果运行结果没出来, 就需要等待结果出来, 建议先看下 Thread-Per-Message 模式 多线程基础之设计模式Thread-Per-Message模式_canxiusi的博客-CSDN博客

二. 示例程序

类名 说明
Main 测试程序类
Host 向请求返回FutureData的实例的类
Data 表示访问数据的方法的接口, 有FutureData和RealData实现该接口
FutureData 表示RealData的 "提货单" 类, 其他线程会创建RealData的实例
RealData 表示实际数据的类, 构造函数的处理会花费很长时间

2.1 Main类

Main 类会调用 request() 方法三次, 接着他会接收三个 Data 实例作为返回值, 实际上都是 FutureData 的实例, 无需花费时间即可获取他们, 类似蛋糕的提货单

/*** @author canxiusi.yan* @description Main* @date 2022/6/6 22:11*/
public class Main {public static void main(String[] args) {System.out.println("main begin");Host host = new Host();Data futureData1 = host.request(10, 'a');Data futureData2 = host.request(20, 'b');Data futureData3 = host.request(30, 'c');try {Thread.sleep(2000);} catch (InterruptedException e) {//}System.out.println("futureData1.getContent() = " + futureData1.getContent());System.out.println("futureData2.getContent() = " + futureData2.getContent());System.out.println("futureData3.getContent() = " + futureData3.getContent());System.out.println("main end");}
}

2.2 Host类

会创建 FutureData 的实例, 启动一个新线程, 用于创建 ReadData 的实例, 将 FutureData 的实例作为返回值返回给调用者, 如直接调用 RealData 的实例相比, 这三项操作的处理事件都非常短, 因此, 调用 request 方法的线程可以很快从方法中返回

/*** @author canxiusi.yan* @description Host* @date 2022/6/6 22:11*/
public class Host {public Data request(final int count, final char c) {System.out.println("   request(" + count + ", " + c + ")  begin");final FutureData futureData = new FutureData();// 这里模拟程序, 就先显式创建线程池new Thread(() -> {RealData realData = new RealData(count, c);futureData.setRealData(realData);}).start();return futureData;}
}

2.3 Data接口

FutureData 和 RealData 实现了该接口

/*** @author canxiusi.yan* @description Data* @date 2022/6/6 22:12*/
public interface Data {abstract String getContent();
}

2.4 FutureData类

FutureData 类表示 "提货单" 的类, realData 字段是用于保存稍后创建完毕的 ReadData 的实例的字段, 我们可以通过 setReadData 方法设置该字段

ready 字段表示是否已经为 readData 赋值的字段, 为 true 时, 表示蛋糕制作完成了

/*** @author canxiusi.yan* @description FutureData* @date 2022/6/6 22:12*/
public class FutureData implements Data {private RealData realData;private boolean ready = false;public synchronized void setRealData(RealData realData) {// 已经存在结果(蛋糕)if (ready) {return;}this.realData = realData;this.ready = true;notifyAll();}@Overridepublic synchronized String getContent() {while (!ready) {try {wait();} catch (InterruptedException e) {//}}return realData.getContent();}
}

2.5 ReadData类

ReadData 类是一个需要花费很长时间才能创建好的实例类, Future 模式就是为了这样的 "需要花费很长时间进行处理的普通的类" 生成一张 "提货单", 并通过多线程来提高程序性能的模式

/*** @author canxiusi.yan* @description RealData* @date 2022/6/6 22:12*/
public class RealData implements Data {private final String content;public RealData(int count, char c) {System.out.println(" making RealData(" + count + ", " + c + ")  begin");char[] buffer = new char[count];for (int i = 0; i < count; i++) {buffer[i] = c;try {Thread.sleep(100);} catch (InterruptedException e) {//}}System.out.println(" making RealData(" + count + ", " + c + ")  end");this.content = new String(buffer);}@Overridepublic String getContent() {return content;}
}

2.6 运行示例

        从图中可以看出, 3次request() 方法就立即停止了, 这与 Thread-Per-Message 模式运行结果相同, RealData 的实例是在新线程中创建的, 在主线程进行其他处理的同时, RealData 的实例也在被慢慢创建, 接着主线程会调用 getContent() 方法, 如果 RealData 实例创建好了, 程序会立即打印内容, 如果还没创建好, 则会继续等待

main beginrequest(10, a)  beginrequest(20, b)  beginrequest(30, c)  beginmaking RealData(10, a)  beginmaking RealData(30, c)  beginmaking RealData(20, b)  beginmaking RealData(10, a)  end
futureData1.getContent() = aaaaaaaaaamaking RealData(20, b)  end
futureData2.getContent() = bbbbbbbbbbbbbbbbbbbbmaking RealData(30, c)  end
futureData3.getContent() = cccccccccccccccccccccccccccccc
main end

三. Future模式中的登场的角色

3.1 Client(请求者)

Client 想 Host 发出请求, 并会立即接收到请求的处理结果(返回值)

3.2 Host

Host 角色会创建新的线程, 并开始在新的线程中创建 RealData, 同时 他会将 Future 角色返回给 Client 角色, 在实例程序中, 有 Host 类扮演此角色

3.3 VirtualData(虚拟数据)

VirtualData 角色能让 Future 角色与 RealData 角色具有一致性, 在示例程序中, 由 Data 扮演

3.4 ReadData(真实数据)

RealData 角色表示真是数据的角色, 创建该对象需要花费很长的时间, 在示例程序中, 由  ReadData 类扮演该角色

3.5 Future(期货)

Future 是 RealData 的 "提货单", 由 Host 角色传递给 Client, 从程序行为上看, 对 Client 而言, Future 角色就是 VirtualData

3.5 模式类图

四. java.util.concurrent包和Future模式

下面使用 java.util.concurrent 包来改写前面的示例程序, 需要修改的只有 Host 类和 FutureData 类

4.1 通过java.util.concurrent包改造Host类

这里传递给 FutureData 的构造函数的参数是 Callable 对象, 他的 call() 方法处理的是 "创建新的 RealData 的实例并返回给调用者, (1) 中只是创建了 FutureData 的实例, 创建 RealData 的实例的实际处理还没开始, (2) 中创建并启动一个线程, 用于真正的创建 RealData 的实例, 这里启动的新线程会调用 Callable 的 call() 方法, 然后 set 值

/*** @author canxiusi.yan* @description Host* @date 2022/6/6 22:11*/
public class Host {public Data request(final int count, final char c) {System.out.println("   request(" + count + ", " + c + ")  begin");// (1)final FutureData futureData = new FutureData(new Callable<RealData>() {@Overridepublic RealData call() throws Exception {return new RealData(count, c);}});// (2)new Thread(futureData).start();return futureData;}
}

4.2 通过java.util.concurrent包改造FutureData类

FutureData 类继承了 java.util.concurrent.FutureTask 类, 构造函数接收到返回值 Callable 对象会直接传递给父类 FutureTask, 由于 call() 方法的调用被交给了 FutureTask 类, 所以也无需在 FutureData 中编写相关的代码

/*** @author canxiusi.yan* @description FutureData* @date 2022/6/6 22:12*/
public class FutureData extends FutureTask<RealData> implements Data {public FutureData(Callable<RealData> callable) {super(callable);}@Overridepublic String getContent() {try {return get().getContent();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}return null;}
}

4.3 使用了java.util.concurrent包以后的程序时序图

多线程基础之设计模式Future模式相关推荐

  1. java多线程系列13 设计模式 Future 模式

    Future 模式 类似于ajax请求  页面异步的进行后台请求 用户无需等待请求的结果 就可以继续浏览或者操作 核心就是:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑 ...

  2. 多线程基础之设计模式Producer-Consumer模式

    一. Producer-Consumer介绍 producer 是 "生产者" 的意思, 指的是生产线程的数据, Consumer 是 "消费者" 的意思, 指 ...

  3. 多线程设计模式 - Future模式

    Future模式是多线程开发中非常常见的一种设计模式,它的核心思想是异步调用.这类似我们日常生活中的在线购物流程,带在购物网看着一件商品时可以提交表单,当订单完成后就可以在家里等待商品送货上门.或者说 ...

  4. java 多线程 临界区_多线程编程的设计模式 临界区模式

    临界区模式 Critical Section Pattern 是指在一个共享范围中只让一个线程执行的模式. 它是所有其它多线程设计模式的基础,所以我首先来介绍它. 把着眼点放在范围上,这个模式叫临界区 ...

  5. 多线程设计模式(二):Future模式

    一.什么是Future模型: 该模型是将异步请求和代理模式联合的模型产物.类似商品订单模型.见下图: 客户端发送一个长时间的请求,服务端不需等待该数据处理完成便立即返回一个伪造的代理数据(相当于商品订 ...

  6. Java多线程编程中Future模式的详解

    转载自 https://www.cnblogs.com/winkey4986/p/6203225.html Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker ...

  7. Java程序性能优化 读书笔记(十)并行设计模式:Future模式

    转载:Java多线程编程中Future模式的详解<转> 参考:葛一鸣,Java程序性能优化.清华大学出版社. 随着多核时代的到来,CPU的并行能力有了很大的提升.在这种背景下,传统的串行程 ...

  8. Java多线程基础学习,Thread解读、java线程的状态、同步和异步、两阶段终止模式

    理论概述 单线程和多线程 为什么要使用多线程呢?多线程有什么好处呢? 如果在程序中,需要读写一个文件,该文件很大,那我们执行到该io操作时,cpu就会等待该io操作执行完才会继续运行下面的代码,进程调 ...

  9. 学习多线程中的 Future 模式一篇文章就够了 !!!

    文章目录 一.Future 模式 二.Future模式的主要角色 三.Future模式的简单实现 四.JDK中的Future模式 五.Guava对Future模式的支持 一.Future 模式 Fut ...

最新文章

  1. java ls_linux ls 命令
  2. wampserver3.0.6 外网 不能访问
  3. 【华为云技术分享】前端工程师必备:从浏览器的渲染到性能优化
  4. Visual C# .Net 环境中编程实现浮动工具栏
  5. python之optparse模块
  6. MapGuide open source开发系列教程四: 体系结构(转贴)
  7. VUE调用打印机打印页面
  8. 分布式系统的完整介绍
  9. imagej得到灰度图数据_Java图像处理最快技术:ImageJ 学习第一篇
  10. 三极管原理-导通条件
  11. 单片机基础实验六则(汇编)
  12. A. 旅馆顾客统计(静态成员)
  13. echarts markline X轴 Y轴 添加标识线
  14. Python 01--介绍、基本语法、流程控制
  15. 星期几计算函数参考 周几计算 礼拜几计算函数 C语言 C++函数参考 用公式计算 通用函数 Linux开发函数 Windows开发函数参考
  16. mysql的基础查阅
  17. php保存文件乱码,如何解决php保存文件乱码的问题
  18. 《老梁四大名著情商课》笔记- 别慌,情商是可以提升的
  19. java_枚举类型(支付方式枚举)
  20. 华为服务器gpu卡型号,gpu服务器 华为云

热门文章

  1. 深度学习-场景、数据、模型
  2. 鸿蒙系统游戏跟安卓互通吗,鸿蒙系统玩游戏跟安卓互通吗
  3. 重装计算机硬件,计算机重装系统的详细步骤
  4. 报错vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: “TypeError: Cannot read property ‘length‘
  5. 另一个用户已连接到此计算机,如何远程控制另一台电脑 远程控制另一台电脑方法【详解】...
  6. python后端开发流程_2019 Python后端开发面经总结
  7. IDEA控制台乱码解决
  8. 2021年3月全国MySQL二级考试笔记
  9. Python type(anyObj) 函数与 types 模块
  10. Struts2--ONGL--值栈