文章内容
1、什么是Future模式
当某一程序提交了一个请求,期望得到一个答复,但是这个请求需要处理的时间可能很长,传统模式下这个请求是同步的,客户端必须等待请求响应之后才能执行其他操作。而在Future模式下客户端立刻拿到一个伪造的数据(相当于商品的订单,而非商品本身),而客户端在此期间可以调用其他业务逻辑,充分的利用了等待时间,这就是Future模式的核心所在。这样在整个调用过程中,就不存在无谓的等待,充分的利用了所有的时间片,从而提高了整体的响应速度。
举个例子,在金融行业叫期权,市场上有看跌期权和看涨期权,你可以在现在(比如九月份)购买年底(十二月)的石油,假如你买的是看涨期权,那么如果石油真的涨了,你也可以在十二月份依照九月份商定的价格购买。扯远了,Future就是你可以拿到未来的结果。对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果是再取真实的结果。
2、场景示例
场景一:
午饭时间到了,同学们要去吃饭了,小王下楼,走了20分钟,来到了肯德基,点餐,排队,吃饭一共花了20分钟,又花了20分钟走回公司继续工作,合计1小时。
场景二:
午饭时间到了,同学们要去吃饭了,小王点了个肯德基外卖,很快,他就拿到了一个订单(虽然订单不能当饭吃,但是有了订单,还怕吃不上饭嘛)。接着小王可以继续干活,30分钟后,外卖到了,接着小王花了10分钟吃饭,接着又可以继续工作了,成功地卷到了隔壁的小汪。
在这两个场景中,小王的工作时间更加紧凑,特别是那些排队的时间都可以让外卖员去干,因此可以更加专注于自己的本职工作。场景1就是典型的函数同步调用,而场景2是典型的异步调用。
而场景2的异步调用,还有一个特点,就是它拥有一个返回值,这个返回值就是我们的订单。这个订单很重要,凭借着这个订单,我们才能够取得当前这个调用所对应的结果。
这里的订单就如同Future模式中的Future,这是一个合约,一份承诺。虽然订单不能吃,但是手握订单,不怕没吃的,虽然Future不是我们想要的结果,但是拿着Future就能在将来得到我们想要的结果。
因此,Future模式很好地解决了那些需要返回值的异步调用。
3、模式解析
- Main:向Client发出请求
- Host:返回Data数据,立即返回FutureData,去开启 ClientThread线程装配RealData
- Data:返回数据接口
- FutureData:Future数据构造很快,但是是一个虚拟的数据,需要装配RealData
- RealData:真是数据
4、Future模式代码实现
public interface Data {
public abstract String getContent() throws InterruptedException;
}
public class RealData implements Data {
private final String content;
public RealData(int count,char c) {
System.out.println("开始初始化 RealData……");
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
sb.append(c);
}
System.out.println("RealData初始化完成……");
this.content = sb.toString();
}
@Override
public String getContent() {
return this.content;
}
}
public class FutureData implements Data {
private RealData realData = null;
private boolean flag = false;
public synchronized void setRealData(RealData realData){
if (flag){
return;
}
// 当获取到数据后,
this.realData = realData;
this.flag = true;
notifyAll();
}
@Override
public String getContent() {
while (!flag){
try {
this.wait(); //
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return realData.getContent();
}
}
public class Host {
public Data request(final int count, final char c){
System.out.println(" request(" + count + ", " + c +" ) BEGIN");
final FutureData future = new FutureData();
new Thread(
(() -> {
RealData realdata = new RealData(count, c);
future.setRealData(realdata);
}))
.start();
System.out.println(" request(" + count + ", " + c + ") END");
return future;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
// write your code here
System.out.println("main begin");
Host host = new Host();
Data data1 = host.request(10, 'A');
Data data2 = host.request(20, 'B');
Data data3 = host.request(30, 'C');
System.out.println("main otherJob BEGIN");
try {
Thread.sleep(2000);
} catch (InterruptedException e){}
System.out.println("main otherJob END");
System.out.println("data1 = " + data1.getContent());
System.out.println("data2 =" + data2.getContent());
System.out.println("data3 =" + data3.getContent());
System.out.println("main END");
}
}
执行结果:
main begin
request(10, A ) BEGIN
request(10, A) END
request(20, B ) BEGIN
request(20, B) END
request(30, C ) BEGIN
request(30, C) END
main otherJob BEGIN
开始初始化 RealData……
开始初始化 RealData……
RealData初始化完成……
开始初始化 RealData……
RealData初始化完成……
RealData初始化完成……
main otherJob END
data1 = AAAAAAAAAA
data2 =BBBBBBBBBBBBBBBBBBBB
data3 =CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
main END