当前位置: 首页 > news >正文

Future 模式简介

简介

Future 模式是多线程开发中的一种常见设计模式,它的核心思想是异步调用。

比如我们在网上购物,付款后就会产生一个订单,之后你该干嘛干嘛,快递小哥会上门送货,而不必像在超市结账那样,付款后要等着收银员打出小票再帮你打包商品,这个时间你只能站那等着。

总的来说,Future 模式无法立即给出你想要的结果,但它会给你一个契约,之后你可以随时通过这个契约来获取你想要的结果。

例子

下边举个简单的例子:

例子中,Data 接口有两个实现类,RealData 表示真实的数据也就是最终想要的,FutureData 表示一个契约,通过这个 FutureData 可以获得 RealData 的真实数据。

FutureData:

 1 package com.zhengbin.springboot.future;
 2 
 3 /**
 4  * Created by zhengbin on 2017/11/14
 5  */
 6 public class FutureData implements Data {
 7     private RealData realData = null;
 8     private boolean isReady = false;
 9 
10     public synchronized void setRealData(RealData realData) {
11         if (isReady) {
12             return;
13         }
14         this.realData = realData;
15         isReady = true;
16         notifyAll();
17     }
18 
19     @Override
20     public synchronized String getResult() {
21         while (!isReady) {
22             try {
23                 wait();
24             } catch (InterruptedException e) {
25             }
26         }
27         return realData.getResult();
28     }
29 }

FutureData 相当于 RealData 的代理(契约),封装了获取 RealData 等待的过程。

调用 getRealData 方法时,如果数据还没有准备好,线程就会等待(阻塞),当执行 setRealData 后,将会唤醒所有等待(阻塞)中的线程,这时才能获取到数据。

RealData:

 1 package com.zhengbin.springboot.future;
 2 
 3 /**
 4  * Created by zhengbin on 2017/11/14
 5  */
 6 public class RealData {
 7     private final String result;
 8 
 9     public RealData(String param) {
10         StringBuffer sb = new StringBuffer();
11         for (int i = 0;i < 10;i++) {
12             sb.append(param);
13             try {
14                 Thread.sleep(300);
15             } catch (InterruptedException e) {
16             }
17         }
18         result = sb.toString();
19     }
20 
21     public String getResult() {
22         return result;
23     }
24 }

RealData 的构造函数,模拟了一个数据构成很慢的过程。

Client:

 1 package com.zhengbin.springboot.future;
 2 
 3 /**
 4  * Created by zhengbin on 2017/11/14
 5  */
 6 public class Client {
 7     public Data request(final String requestStr) {
 8         final FutureData futureData = new FutureData();
 9         new Thread() {
10             @Override
11             public void run() {
12                 RealData realData = new RealData(requestStr);
13                 futureData.setRealData(realData);
14             }
15         }.start();
16         return futureData;
17     }
18 }

Client 就是我们调用的客户端,实现了获取 FutureData,并开启构造 RealData 的线程,该线程单独执行,主线程直接返回,只不过返回的是一个契约也就是 FutureData,真正的数据 RealData 则在另一个单独的线程中缓慢的构造,构造完成后就会通过 FutureData 的 setRealData 将真实数据保存,这样客户端就可以 get 到真实数据了。

FutureTest:

 1 package com.zhengbin.springboot.future;
 2 
 3 /**
 4  * Created by zhengbin on 2017/11/14
 5  */
 6 public class FutureTest {
 7     public static void main(String[] args) throws InterruptedException {
 8         Client client = new Client();
 9         Data futureData = client.request("zhengbin");
10         System.out.println("request done...");
11         Thread.sleep(500);
12         System.out.println("other done...");
13         System.out.println("result : "+futureData.getResult());
14     }
15 }

测试方法通过 Client 发起调用,调用后模拟执行其他的逻辑,耗费 0.5 秒,之后需要用到 Data 的数据了,但构造真实数据的时间需要 3 秒,此时主线程就会阻塞在这里,等待真实数据的构造完成。

这种方式就给了主线程去执行其他任务的时间,节省了 0.5 秒的时间,可以用来去做别的事情。

参考资料

[1] 实战 Java 高并发程序设计 5.5

相关文章:

  • 【24】线程池
  • 内存优化问题
  • NPM测试模块之rewire教程
  • 解决PHP编译cURL的reinstall the libcurl问题
  • 关于selenium webdriver chromedriver下载的问题
  • php多进程实现
  • hihoCoder 1513 小Hi的烦恼
  • 生鲜电商大乱斗,谁生在了终点线?
  • 华为实验作业:冗余链路、虚拟路由冗余协议 2018/1/23
  • Mac上的远程控制软件——TeamViewer
  • openlayers3 自定义鹰眼缩略图
  • Java基础1(String StringBuilder StringBuffer 三者区别)
  • java调用webservice接口 几种方法
  • 10.6-10.10 监控io、free命令、ps命令、查看网络状态和抓包
  • Linux的头文件和C/C++的头文件
  • 【node学习】协程
  • 【React系列】如何构建React应用程序
  • 【笔记】你不知道的JS读书笔记——Promise
  • ESLint简单操作
  • Git同步原始仓库到Fork仓库中
  • JavaScript 基础知识 - 入门篇(一)
  • JavaScript创建对象的四种方式
  • JS基础之数据类型、对象、原型、原型链、继承
  • Linux快速复制或删除大量小文件
  • Mysql5.6主从复制
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • Puppeteer:浏览器控制器
  • Python利用正则抓取网页内容保存到本地
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 听说你叫Java(二)–Servlet请求
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 移动端 h5开发相关内容总结(三)
  • 以太坊客户端Geth命令参数详解
  • 译自由幺半群
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • # 安徽锐锋科技IDMS系统简介
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (ZT)薛涌:谈贫说富
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (四)模仿学习-完成后台管理页面查询
  • (一)Neo4j下载安装以及初次使用
  • (原創) 未来三学期想要修的课 (日記)
  • (正则)提取页面里的img标签
  • (转)Windows2003安全设置/维护
  • .apk文件,IIS不支持下载解决
  • .Mobi域名介绍
  • .NET Reactor简单使用教程
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • [ C++ ] template 模板进阶 (特化,分离编译)
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [20140403]查询是否产生日志