一、什么是Future模型:
该模型是将异步请求和代理模式联合的模型产物。类似商品订单模型。见下图:
客户端发送一个长时间的请求,服务端不需等待该数据处理完成便立即返回一个伪造的代理数据(相当于商品订单,不是商品本身),用户也无需等待,先去执行其他的若干操作后,再去调用服务器已经完成组装的真实数据。该模型充分利用了等待的时间片段。
二、Future模式的核心结构:
Main:启动系统,调用Client发出请求;
Client:返回Data对象,理解返回FutureData,并开启ClientThread线程装配RealData;
Data:返回数据的接口;
FutureData:Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData;
RealData:真实数据,构造比较慢。
以上转载于:https://blog.youkuaiyun.com/lmdcszh/article/details/39696357
代码实现
1.首先定义接口
/** * Created by 13102 on 2018/4/5. * 定义获取结果的接口 */ public interface Data { String getResult(); }
2.定义包装类对象,当client端发起请求时,直接返回包装类对象,即FutureData对象,注意在包装类对象中实现了Data
接口,使用了wait()和notifyAll()方法,也就是说在client端调用getResult()函数时,调用的是FutureData的方法,当真正的RealData没有构造完成后,它一直处于wait()状态,而构造完成后,它就会被setRealData()方法里面的notifyAll()唤醒,返回真正的查询结果.
/** * Created by 13102 on 2018/4/5. * 什么是Future模型 * future模式是客户端发出一个请求,服务端不需要等待,而是直接返回一个伪造的代理数据,用户也不需要等待 * 可以先去做其他事情 * 包含以下几部分 * <p> * Main:启动系统,调用Client发出请求; * <p> * Client:返回Data对象,理解返回FutureData,并开启ClientThread线程装配RealData; * <p> * Data:返回数据的接口; * <p> * FutureData:Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData; * <p> * RealData:真实数据,构造比较慢。 */ public class FutureData implements Data { private RealData realData; //持有一个真实数据的data对象 private boolean isReady = false; public synchronized void setRealData(RealData realData) { //如果已经装载完成,就直接返回 while (isReady) { return; } //如果没有装载就进行装载真实对象 this.realData = realData; isReady = true; //通知等待的线程 notifyAll(); } @Override public synchronized String getResult() { //如果没有装载完成就进行等待 while (!isReady) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //否则返回真实数据 return this.realData.result; } }
3.定义真实类对象,在真实类对象中执行真正的操作
/** * Created by 13102 on 2018/4/5. * 真实类对象,真实类对象需要实现Data接口,在方法中返回真实的结果 */ public class RealData implements Data { protected String result; public RealData(String queryPara) { System.out.println("根据"+queryPara+"查询,这是一个很耗时的操作"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("查询完成"); result = "查询结果"; } @Override public String getResult() { return result; } }
4.定义client端,发起request请求,首先直接返回代理对象,然后后台起一个线程执行真正的对象的获取;
/** * Created by 13102 on 2018/4/5. * 客户端,根据请求的参数,首先返回一个代理的data对象,然后后台创建一个线程去执行真正的查询 */ public class FutrueClient { public Data request( final String queryPara) { //首先构造一个代理对象,先将代理对象返回给客户端 final FutureData futureData = new FutureData(); //后台开启线程执行真正的查询 new Thread(()->{ //真正的RealData对象执行查询,查询完成后将真实realData放回给代理对象 RealData realData = new RealData(queryPara); futureData.setRealData(realData); }).start(); //首先放回代理对象 return futureData; } }
5.定义Main端,调用client端,然后再返回真实结果之前,可以做其他事情;
/** * Created by 13102 on 2018/4/5. * 主函数 */ public class Main { public static void main(String[] args) { FutrueClient client=new FutrueClient(); System.out.println("请求查询"); Data data = client.request("参数abc"); System.out.println("进行其他操作"); // System.out.println("准备获取真实数据"); String result = data.getResult(); System.out.println("获得的结果是"+result); } }
程序的运行结果
请求查询
进行其他操作
根据参数abc查询,这是一个很耗时的操作
查询完成
获得的结果是查询结果
个人总结: 感觉Future这种设计模式很巧妙,可以很好的利用执行耗时操作的时间,普通程序此时只能等待,而Future模式可以更好的利用这段时间,在这个时间它可以去做其他的事情,而future恰好有未来的意思.