14.Java中的Future模式
jdk1.7.0_79
本文实际上是对上文《13.ThreadPoolExecutor线程池之submit方法》的一个延续或者一个补充。在上文中提到的submit方法里出现了FutureTask,这不得不停止脚步将方向转向Java的Future模式。
Future是并发编程中的一种设计模式,对于多线程来说,线程A需要等待线程B的结果,它没必要一直等待B,可以先拿到一个未来的Future,等B有了结果后再取真实的结果。
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(callable); //主线程需要callable线程的结果,先拿到一个未来的Future
System.out.println(future.get()); //有了结果后再根据get方法取真实的结果,当然如果此时callable线程如果没有执行完get方法会阻塞执行完,如果执行完则直接返回结果或抛出异常
也就是说,Future它代表一个异步计算的结果。

上面就代表了Future模式的执行原理,根据网上的例子,我们可以来自己实现一个Future模式。
package com.future; /**
* 数据结果
* Created by yulinfeng on 6/18/17.
*/
public interface Data {
String getResult() throws InterruptedException;
}
package com.future; /**
* 结果的真实计算过程
* Created by yulinfeng on 6/18/17.
*/
public class RealData implements Data {
protected String data; public RealData(String data) {
try {
System.out.println("正在计算结果");
Thread.sleep(3000); //模拟计算
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = data + “ world”;
} public String getResult() throws InterruptedException {
return data;
}
}
package com.future; /**
* 真实结果RealData的代理
* Created by yulinfeng on 6/18/17.
*/
public class FutureData implements Data {
RealData realData = null; //对RealData的封装,代理了RealData
boolean isReady = false; //真实结果是否已经准备好 public synchronized void setResultData(RealData realData) {
if (isReady) {
return;
}
this.realData = realData;
isReady = true;
notifyAll(); //realData已经被注入到了futureData中,通知getResult方法
} public synchronized String getResult() throws InterruptedException {
if (!isReady) {
wait(); //数据还未计算好,阻塞等待
}
return realData.getResult();
}
}
package com.future; /**
* Client主要完成的功能包括:1. 返回一个FutureData;2.开启一个线程用于构造RealData
* Created by yulinfeng on 6/18/17.
*/
public class Client { public Data request(final String string) {
final FutureData futureData = new FutureData(); /*计算过程比较慢,单独放到一个线程中去*/
new Thread(new Runnable() { public void run() {
RealData realData = new RealData(string);
futureData.setResultData(realData);
}
}).start(); return futureData; //先返回一个“假”的futureData
}
}
/**
* 负责调用Client发起请求,并使用返回的数据。
* Created by yulinfeng on 6/18/17.
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
Client client = new Client();
System.out.println("准备计算结果");
Data data = client.request("hello"); //立即返回一个“假”的futureData,可以不用阻塞的等待数据返回,转而执行其它任务
System.out.println("执行其它任务");
Thread.sleep(3000); //模拟执行其它任务
System.out.println("数据的计算结果为:" + data.getResult());
}
}
仔细阅读以上程序对Future模式的实现不难发现,Future模式是异步请求和代理模式的结合。当然在JDK中已经为我们实现好了Future模式。
修改RealData类:
package com.future; import java.util.concurrent.Callable; /**
* 结果的真实计算过程
* Created by yulinfeng on 6/18/17.
*/
public class RealData2 implements Callable<String> {
protected String data; public RealData2(String data) {
this.data = data;
}
public String call() throws Exception {
try {
System.out.println("正在计算结果");
Thread.sleep(2000); //模拟计算结果
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = data + " world";
return data;
}
}
修改Main测试类:
package com.future; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; /**
* 负责调用Executor的submit,并使用返回的数据。
* Created by yulinfeng on 6/18/17.
*/
public class Main2 { public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService client = Executors.newSingleThreadExecutor(); //类似Client
System.out.println("准备计算结果");
Future<String> data = client.submit(new RealData2("hello")); //类似Client.request
System.out.println("执行其它任务");
Thread.sleep(3000);
System.out.println("数据的计算结果为:" + data.get());
}
}
现在回到上文还未解决完的AbstractExecutorService#submit方法。
类比上面的Client#request方法,在Client#request中先创建一个FutureData实例,而在AbstractExecutorService#submit中则是创建一个FutureTask实例,接着Client#request新创建一个线程用于异步执行任务,并直接返回FutureData,而在AbstractExecutorService#submit中同样也将任务交给了execute方法,并直接返回FutureTask。当然JDK中Future模式的实现更为复杂。
在《12.ThreadPoolExecutor线程池原理及其execute方法》中我们讲解了execute方法,在ThreadPoolExecutor$Worker#runWorker方法第1145行中是对task任务的调用:
//ThreadPoolExecutor$Worker#runWorker
task.run();
submit调用execute以执行run方法,实际执行的是FutureTask中的run方法。在FutureTask#run中,可以看到对任务Callable类型的task异步的执行,以及结果的保存。
14.Java中的Future模式的更多相关文章
- Java中的Future模式原理自定义实现
摘要:Future模式类似于js中的ajax等,是一个异步获取数据的机制,这里我把自己的一些形象理解通过代码实现了一下.该机制可以形象的理解为:调用获取数据的方法,首先获得一个没有装数据的空箱子(这个 ...
- (转)轻松学,Java 中的代理模式及动态代理
背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...
- Java中的Future相关
先上一个场景:假如你突然想做饭,但是没有厨具,也没有食材.网上购买厨具比较方便,食材去超市买更放心. 实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材.所以,在主线程里面另起一个子线 ...
- java中 immutable,future,nio
什么是Future? 用过Java并发包的朋友或许对Future (interface) 已经比较熟悉了,其实Future 本身是一种被广泛运用的并发设计模式,可在很大程度上简化需要数据流同步的并发应 ...
- Java中的代理模式
代理模式在Java Web的框架中经常使用到.比如说在对数据库的访问中,核心功能是对数据库的增删改查,而连接数据库.处理事务等功能我们在开发中也要考虑到.所以我们将数据库的CRUD抽象到接口中,然后实 ...
- 说说Java中的代理模式
今天看到传智播客李勇老师的JDBC系列的第36节——通过代理模式来保持用户关闭连接的习惯.讲的我彻底蒙蔽了,由于第一次接触代理模式,感到理解很难,在博客园找到一篇文章,先记录如下: 引用自java设计 ...
- 谈谈Java中的代理模式
首先来看一下代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是代理类与 ...
- java中的dao模式
java中Dao模式 什么是DAO 1.Data Access Object(数据存取对象) 2.位于业务逻辑和持久化数据之间 3.实现对持久化数据的访问 DAO模式的作用 1隔离业务逻辑代码 ...
- Java中的单利模式
单利模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创 ...
随机推荐
- 如何使用python生成xml
最近要用python生成一个xml格式的文件.因为有一些内容是中文,原来的xml文件中使用了CDATA 的部分. 而之前的python程序所用的库中没有 创建这个区域的方法.无奈研究了大半天. 最后用 ...
- 【Spark2.0源码学习】-5.Worker启动
Worker作为Endpoint的具体实例,下面我们介绍一下Worker启动以及OnStart指令后的额外工作 一.脚本概览 下面是一个举例: /opt/jdk1..0_79/ ...
- jenkins 使用注意
在jenkins使用的时候,在输入文件地址的时候,文件各级目录不能有空格等特殊符号!否则报错!
- IOS中常用的UIColor
UIColor + (UIColor *)blackColor; // 0.0 white 黑色 + (UIColor *)darkGrayColor; // 0.333 white 深灰色 + (U ...
- IOS开发常见错误
. 问题表现:什么情况?方法居然无法拉线? 问题简述:ios的空间拉线到一个.h .m文件中 居然多次拖动无效.. 问题解决:ios的空间响应单单在代码中创建一个方法是没用的,这个时候通常跟空间是没有 ...
- Day3 Pyhon的六大数据类型
Python3 中有六个标准的数据类型: Number(数字) String(字符串) List(列表) Tuple(元组) Sets(集合) Dictionary(字典) Number(数字) Py ...
- iframe框架的应用
同学接私活,我写几个页面. 后台系统,点击侧栏菜单后,右边div的要显示对应的内容.就是说,没选一下左边的菜单,右边的内容都要变化. 这次首先尝试了一下Oldfasional办法--iframe框架. ...
- java下蛇形回环矩阵的实现
前文废话:这个问题据说是腾讯之前的一道笔试题,由于当时没认真看,现在记不清这种矩阵是不是叫"蛇形回环矩阵"......请大家直接看图1,就是那个样子的矩阵. 问题描述:输入一个N, ...
- Memcache服务搭建
Memcache Memcache的作用网上资料都讲的很好,说简单点就是减轻读取数据库的压力,原理也很简单: 被请求的数据会先到memcache里去取,如果没有就去数据库里取,顺便给memcache带 ...
- CMD和seaJS
前面的话 CMD(Common Module Definition)表示通用模块定义,该规范是国内发展出来的,由阿里的玉伯提出.就像AMD有个requireJS,CMD有个浏览器的实现SeaJS,Se ...