Future是多线程开发中一种常用的设计模式,它的核心思想是异步调用。去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑。
例如如下的请求调用过程时序图。当call请求发出时,需要很长的时间才能返回。左边的图需要一直等待,等返回数据后才能继续其他操作;而右边的Future模式的图中客户端则无需等到可以调用其他业务逻辑,充分利用了等待时间。服务器段接收到请求后立即返回结果给客户端,这个结果并不是真实的结果(而是真实结果的代理),也就是先获得一个假数据,然后执行其他操作。
下面给出一个Future的简单实现
Data:返回数据的接口
RealData:真实数据,其构造是比较慢的
FutureData:Future数据,构造很快,是一个虚拟的数据,需要用来装配RealData.
Client:返回Data对象,立即返回FutureData,开启装配RealData线程
Main:系统启动,调用client请求
Data的实现
//无论是FutureData还是RealData都实现该接口。 public interface Data { String getResult() throws InterruptedException; }FutureData的实现
//FutureData是Future模式的关键,它实际上是真实数据RealData的代理,封装了获取RealData的等待过程 public class FutureData implements Data { RealData realData = null; //FutureData是RealData的封装 boolean isReady = false; //是否已经准备好 public synchronized void setRealData(RealData realData) { if(isReady) return; this.realData = realData; isReady = true; notifyAll(); //RealData已经被注入到FutureData中了,通知getResult()方法 } @Override public synchronized String getResult() throws InterruptedException { if(!isReady) { wait(); //一直等到RealData注入到FutureData中 } return realData.getResult(); } }RealData的实现
public class RealData implements Data { protected String data; public RealData(String data) { //利用sleep方法来表示RealData构造过程是非常缓慢的 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.data = data; } @Override public String getResult() { return data; } }Client的实现
public class Client { public Data request(final String string) { final FutureData futureData = new FutureData(); new Thread(new Runnable() { @Override public void run() { //RealData的构建很慢,所以放在单独的线程中运行 RealData realData = new RealData(string); futureData.setRealData(realData); } }).start(); return futureData; //先直接返回FutureData } }Main的实现
public class Application { public static void main(String[] args) throws InterruptedException { Client client = new Client(); //这里会立即返回,因为获取的是FutureData,而非RealData Data data = client.request("name"); //这里可以用一个sleep代替对其他业务逻辑的处理 //在处理这些业务逻辑过程中,RealData也正在创建,从而充分了利用等待时间 Thread.sleep(2000); //使用真实数据 System.out.println("数据="+data.getResult()); } }