Future模式是多线程开发中非常常见的一种设计模式,它的核心思想是异步调用。这类似我们日常生活中的在线购物流程,带在购物网看着一件商品时可以提交表单,当订单完成后就可以在家里等待商品送货上门。或者说更形象的是我们发送Ajax请求的时候,页面是异步的进行后台处理,用户无需等待请求的结果,可以继续浏览或操作其他内容。
如上图所示,客户端调用购物请求,服务端程序不等数据处理完成便立即返回客户端一个伪造的数据,(相当于订单,而不是真实的商品)这时候由服务端自己偷偷摸摸的发送了一个other call()请求去获取真实的商品(打包,出库,送货)。这就是Future模式的核心所在。
Future模式的主要角色有:
Main:系统启动,调用FutureClient发出请求
FutureClient:返回Data对象,立即返回FutureData,并开启线程去获取RealData
Data:返回数据的接口
FutureData:虚拟数据,返回很快,需要装载RealData
RealData:真实数据
我们来看代码:
Main:
public class Main { public static void main(String[] args) { FutureClient fc = new FutureClient(); Data data = fc.getRequset("jianzh5"); System.out.println("请求完毕..."); String result = data.getRequest(); System.out.println("返回的结果:"+result); } }
此类主要调用FutureClient的getRequset方法去返回数据
FutureClient:
public class FutureClient { public Data getRequset(final String queryStr){ //初始化代理对象,先返回给客户端 final FutureData futureData = new FutureData(); //启动一个新的线程去加载真实的数据,传递给这个代理对象 new Thread(new Runnable() { @Override public void run() { //此线程去加载真实对象,然后传递给代理对象 RealData realData = new RealData(queryStr); futureData.setRealData(realData); } }).start(); System.out.println("代理对象返回:"+futureData); return futureData; } }
该类在接受到用户请求后很快就能返回虚拟数据 futureData,本身启动一个线程去获取真实数据
RealData:
public class RealData implements Data{ private String result; public RealData(String queryStr){ System.out.println("根据参数: "+queryStr+" 进行查询,这是一个很耗时的操作!"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("装载完毕,获取结果"); result = "查询结果"; } @Override public String getRequest() { return result; } }
RealData装载数据较慢,这里使用Sleep(5000)模拟复杂业务逻辑。
FutureData:
public class FutureData implements Data{ private RealData realData; private boolean isReady = false; public synchronized void setRealData(RealData realData){ //如果已经装载完毕则直接返回 if(isReady){ return; } //如果未装载,进行装载真实数据 this.realData = realData; isReady = true; //通知 notify(); } @Override public synchronized String getRequest() { //如果未装载好一直处于阻塞状态 while (!isReady){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //装载好直接返回数据即可 return this.realData.getRequest(); } }
该类是Future模式的关键,它实际是真实数据RealData的代理,封装了获取RealData的等待过程实际返回的是真实的数据。
JDK内部类已经实现了Future模式,详细内容请看我的另一篇博客《多线程设计模式 – Future模式之JAVA原生实现》。