1 什么是future模式
Future 模式类似于我们发送Ajax请求,这个请求是异步的,用户无需一直做等待,可以先做其他事情,等请求获取到数据,在继续做之前的事情。或者也类似于我们做饭,但是没有厨具,这个时候我们在网上下了订单,网站会提示给你订单已经受理了,但是我们不用一直等待厨具给我们送过来,在等待这个期间,我们可以先买菜,最后厨具到了一起做饭。
那如何实现呢?
首先,客户端Future向服务器发送请求,于此同时,服务器并不会返回真实的数据,他会给你返回一个包装类FutureData,然后服务器开启一个线程请求真实的数据RealData,真实的数据获取完毕,给客户端一个通知,或者客户端可以阻塞其他线程等待真正资源加载完毕。
我们定义一个数据接口Data,无论真实数据RealData和包装类数据FutureData都有继承这个接口。
public interface Data {
String getRequest();
}
接下来我们看一下main方法,它通过调用FutureClient去取获想要的数据RealData,RealData继承Data接口。
public class Main { public static void main(String[] args) throws InterruptedException { FutureClient fc = new FutureClient(); Data data = fc.request("请求参数"); System.out.println("data is " + data); System.out.println("请求发送成功!"); System.out.println("做其他的事情..."); String result = data.getRequest(); System.out.println(result); } }
然后我们看一下FutureClient 是如何帮助我们获取数据的,所有我们看上面的main方法中fc.request("请求参数")中返回的并不是真实的数据,返回的是一个包装类,同时它将启动一个新的线程取请求真实的数据。
public class FutureClient { public Data request(final String queryStr){ //1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情 final FutureData futureData = new FutureData(); //2 启动一个新的线程,去加载真实的数据,传递给这个代理对象 new Thread(new Runnable() { @Override public void run() { //3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象 RealData realData = new RealData(queryStr); futureData.setRealData(realData); } }).start(); return futureData; } }
接下来我们看一下FutureData的实现,他会等待RealData请求完毕,然后发出通知获取真实数据。从而在main方法中的data.getRequest();就可以获取真实的执行结果,这个方法是阻塞线程执行的,因为我们看到在FutureData方法中有wait和notify,只有真正的结果获取到,才能获取到结果。
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