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());
}
}