Future模式是多线程开发中非常常见的一种设计模式,它的核心思想是异步调用。当我们需要调用一个方法时,若该方法比较复杂,执行较慢,那么我们就要一直等待直到该方法执行结束,返回信息。但我们有时候并不急着要这个结果,而希望在这个方法在执行的时候可以做别的事情,而当我们需要这个结果的时候,再去获取这个结果。这个时候我们就可以用的Future模式。
Future模式相当于我们做出请求之后,并不会直接获得真实想要的数据,而是返回了一个契约(比如说,订单),当我们需要这个真实的数据的时候,再通过这个契约去获取真实的数据。再我们没有去拿这个真实数据的时候,程序是可以做其他操作的,这样就不会把时间浪费在等待这个并不急着要的真实数据上。当然,如果我们去获取这个真实数据的时候,该方法还没有执行完毕,这个时候线程才会进入等待。
Future模式的主要参与者:
Main:启动系统,调用Client发出请求;
Client:返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData;
Data:返回数据的接口;
FutureData:Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData;
RealData:真实数据,其构造比较慢,也是我们要的真实数据。
简单实现Future模式的代码如下:
public class Main {
public static void main(String[] args) {
FutureClient futureClient = new FutureClient();
Data submit = futureClient.submit("");
System.out.println("main,数据发送成功");
System.out.println("主线程执行其他任务");
String result = submit.getRequest();
System.out.println("主线程获取数据"+result);
}
}
public class FutureClient {
public Data submit(String reqData){
FetureData fetureData = new FetureData();
new Thread(new Runnable() {
@Override
public void run() {
RealData realData = new RealData("123456");
fetureData.setReadData(realData);
}
}).start();
return fetureData;
}
}
//当有线程想要获取realData的时候,程序会被阻塞。等待RealData被注入才会使用getReal()方法
public class FetureData extends Data{
//读取结果
private boolean FLAG = false;
private RealData realData;
//读取data数据
public synchronized void setReadData(RealData realData){
if(FLAG){
return;
}
//如果flag为false,没有获取到数据,传递readData对象
this.realData = realData;
FLAG = true;
notify();
}
@Override
public synchronized String getRequest() {
while (!FLAG){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return realData.getRequest();
}
}
//获取真实的数据
public class RealData extends Data{
private String result;
public RealData(String reqData) {
System.out.println("正在使用reqData进行网络请求,reqData:" + reqData + ",开始。。。");
try {
//业务操作耗时
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("操作执行完毕。。。获取到结果result");
//获取返回结果
this.result = "result";
}
@Override
public String getRequest() {
return result;
}
}
public abstract class Data {
public abstract String getRequest();
}