Future模式就拿对商品下订单这个操作来说,用户线程A提交订单后,这条用户线程A可以先去干其他的事情,然后再去创建一条B线程去帮这用户创建订单。如果在B线程还没有创建出来订单的时候,用户线程A去调用订单信息,此时线程A会阻塞等待线程B创建出来订单在获取订单信息,否则会直接把线程B创建出来的订单信息返回。再举个实用的栗子:Ajax的异步请求其实很类似Future模式。页面是异步的进行后台处理,用户无须一直等待请求的结果,可以继续浏览或 操作其他内容。
现在代码实现一个Future模式,先看图:
获取数据接口:Data
public interface Data {
// 获取数据的方法
String getRequest();
}
客户端:FutureClient
public class FutureClient {
//发起请求
public Data request(String param){
//1、将包装类先返回给发起请求的客户,告诉他请求已经接收到了,可以去干其他事情了。(其实此时返回给客户端的是一个空对象)
FutureData futureData = new FutureData();
//2、开启一个线程,去查询真实的数据,
new Thread(() -> {
RealData realData = new RealData(param);
futureData.setRequest(realData);
}).start();
//3、快速返回
return futureData;
}
}
数据包装类:FutureData
/**
* 数据包装类
*/
public class FutureData implements Data {
private RealData realData;
private boolean isRealData = false;
//判断是否装载好了数据
//这里需要线程同步(同一时间只能有一个线程操作getRequest(),setRequest(RealData realData)方法)
@Override
public synchronized String getRequest() {
//判断数据是否装载好,如果没有就一直等待下去,
while (!isRealData){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//返回装载好的真实数据
return this.realData.getRequest();
}
public synchronized void setRequest(RealData realData) {
if(isRealData)
return;
this.realData = realData;
isRealData = true;
//唤醒获取数据的线程
notify();
}
}
setRequest(RealData realData),getRequest()方法需要实现线程同步效果,因为有对isRealData属性进行修改,和读取。
真实数据处理类:RealData
/**
* 真实的数据查询类
*/
public class RealData implements Data {
private String result;
//具体查询业务
public RealData(String param) {
System.out.println("根据"+param+"进行查询,这是一个很耗时的操作");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询完毕!");
this.result = "zhangsan";
}
@Override
public String getRequest() {
return this.result;
}
}
main:
public class Main {
public static void main(String[] args) {
//初始化客户端
FutureClient client = new FutureClient();
//发送请求后,立即返回一个结果(没有进行查询)
Data zhangsan = client.request("张三");
//如果没有使用Future模式,此时是处于阻塞状态,需要等待数据查询出来返回结果
System.out.println("发送请求成功!!");
//使用了Future模式就可以干其他事了,(让FutureClient创建的哪个线程去查询)
System.out.println("去干其他事");
//等业务需要其结果的时候,调用getRequest()方法,如果此时那个FutureClient创建的线程查询出来数据,就直接返回,否则阻塞等他查询出来
System.out.println("结果:"+zhangsan.getRequest());
}
}