Future模式的核心是异步调用。它类似于我们商品订单。像我们在网上买了个手机,当我们购买成功后,会生成此订单,此订单信息就是将来取商品的重要凭证,商品无法立即拿到要通过物流寄过来。在此期间,我们就可以接着我们自己的事,等待收货即可。它同时也像我们的Ajax请求的时候,页面是异步的进行后台处理。用户无需等待请求结果,可以继续浏览操作或操作其他内容。
Future模型时序图:
Future模式的主要参与者
参与者 | 作用 |
Main | 系统启动,调用Client发出请求 |
Host | 返回Data对象,并立即返回FutureData,并开启ClientThread线程装配RealData |
Data | 表示访问数据的接口。由FutureData和RealData实现该接口 |
FutureData | Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData |
RealData | 真实数据,构造函数的处理需要花费很长时间 |
Future模型的类图
看第一个类Main
public class Main { public static void main(String[] args) throws InterruptedException { FutureClient fc = new FutureClient(); //先创建Client端的实例 Data data = fc.request("请求参数");//为这个实例装载数据,此时返回的data数据。request相当于是购买商品成功,data相当于订单信息 System.out.println("请求发送成功!"); System.out.println("做其他的事情..."); String result = data.getRequest();//调用之前收到的返回值data的getRequest()方法获取真正的结果,相当于拿着之前的订单信息去取快递 System.out.println(result); } }
在这个类中,会先创建Client实例,将要处理的任务交给Client端去处理,这是立刻收到数据,但此时的是FutureData,而不是RealData。然后自己接着做的事情,最后调用之前收到的返回值data的getRequest()方法获取真正的结果(即之前request方法的处理结果)
第二个 Host(Client端)类
1 public class FutureClient { 2 3 public Data request(final String queryStr){ 4 //1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情 5 final FutureData futureData = new FutureData(); 6 //2 启动一个新的线程,去加载真实的数据,传递给这个代理对象 7 new Thread(new Runnable() { 8 @Override 9 public void run() { 10 //3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象 11 RealData realData = new RealData(queryStr); 12 futureData.setRealData(realData); 13 } 14 }).start(); 15 16 return futureData; 17 } 18 19 }
在这类中会先创建FutureData的实例(futureData)。将这个实例作为返回值返回给调用者。然后会创建一个新的线程并在新线程中创建RealData的实例(realData)。虽然创建RealData的实例需要花费很长时间,但是因为这个实例是在新线程中进行的,并不会影响Main类的处理。当realData创建成功后,线程会调用setRealData()方法,将其放置到futureData中。由于创建RealData会花费一些时间,所以设置futureData字段就是未来的事情了。
第三个Data接口
1 public interface Data { 2 3 String getRequest(); 4 5 }
Data接口是表示数据访问(getContent()方法)的接口
第四个Future类:
1 public class FutureData implements Data{ 2 3 private RealData realData ; 4 5 private boolean isReady = false; 6 7 public synchronized void setRealData(RealData realData) { 8 //如果已经装载完毕了,就直接返回 9 if(isReady){ 10 return; 11 } 12 //如果没装载,进行装载真实对象 13 this.realData = realData; 14 isReady = true; 15 //进行通知 16 notify(); 17 } 18 19 @Override 20 public synchronized String getRequest() { 21 //如果没装载好 程序就一直处于阻塞状态 22 while(!isReady){ 23 try { 24 wait(); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 } 29 //装载好直接获取数据即可 30 return this.realData.getRequest(); 31 } 32 33 34 }
realData字段是用于保存稍后创建完毕的RealData实例的字段,可以通过setRealData方法设置该字段。
ready字段表示是否已经为realData赋值的字段。如果它为true,表示已经为realData赋值。
第五个RealData类
1 public class RealData implements Data{ 2 3 private String result ; 4 5 public RealData (String queryStr){ 6 System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作.."); 7 try { 8 Thread.sleep(5000); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 System.out.println("操作完毕,获取结果"); 13 result = "查询结果"; 14 } 15 16 @Override 17 public String getRequest() { 18 return result; 19 } 20 21 }