Future:未来。个人理解Future模式类似于回调函数,提前返回一个空壳结果,当需要用到这个结果时,再从空壳结果中取得已经计算完成的真实结果。
举个例子:执行某一个功能之后,开启一个新的线程去执行需要计算的返回数据(假设耗时1秒),并且立即返回数据A(这是,数据里没有内容),然后执行后续代码(假设耗时500毫秒)。当后续代码执行到需要用到A时(假设耗时200毫秒),再从数据A中取得数据,这时主线程阻塞在此等待300毫秒,当数据准备完毕调用notify通知主线程,即可得到A的返回数据,继续执行后续操作(总耗时:1秒)。如果不用Future模式串行操作,那么一共耗时1.5秒(1秒计算A,500毫秒执行后续代码)。
Future模式中需要有几个角色
1. 空壳结果(FutureData)
2. 真实结果(RealData),存放结果
3. 空壳与真实结果的实现接口(Data)
4. 未来客户端(用户整合空壳与真实结果,FutureClient)
Data需要提供一个协议,用于取得结果result,FutureData与RealData都实现该协议
package thread_demo_01;
/**
* @Author: yesiming
* @Platform: Mac
* @Date: 3:39 PM 2019/10/10
*/
public interface M_Data {
String getQueryResult();
}
FutueData还需要提供一个设置真实数据的方法,用于真实数据准备完毕后放入到空壳数据中
package thread_demo_01;
/**
* @Author: yesiming
* @Platform: Mac
* @Date: 3:39 PM 2019/10/10
*/
public class M_FutureData implements M_Data {
private M_RealData realData;
private boolean isReady = false;
@Override
public synchronized String getQueryResult() {
while(!isReady) {
try {
wait(); // 如果不用wait和nodify,这里就得轮训判断了。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return this.realData.getQueryResult();
}
public synchronized void setRealData(M_RealData realData) {
// 如果已经处理完成,直接返回
if(isReady) {
return;
}
// 如果没有处理完成,就装载真实对象,然后通知getRequest
this.realData = realData;
isReady = true;
notify();
}
}
先用FutureClient调用空壳数据,未来数据向外提供查询方法query,该方法直接返回新建的未来数据对象,然后新启动一个线程为未来数据对象填充真实数据
package thread_demo_01;
/**
* @Author: yesiming
* @Platform: Mac
* @Date: 3:55 PM 2019/10/10
*/
public class M_FutureClient {
public M_Data query(final String queryStr) {
// 1. 让代理对象先返回给客户端,告诉他们请求已经收到,主线程可以做后续处理了。。。
final M_FutureData futureData = new M_FutureData();
// 2. 启动一个新线程,去家在真实数据,然后传递给代理对象
new Thread(() -> {
M_RealData realData = new M_RealData(queryStr);
futureData.setRealData(realData);
}).start();
return futureData;
}
}
下面是真实结果,这里做耗时的数据处理操作
package thread_demo_01;
/**
* @Author: yesiming
* @Platform: Mac
* @Date: 3:44 PM 2019/10/10
*/
public class M_RealData implements M_Data {
private String result;
/**
* 这里做数据的处理封装,耗时操作
* @param queryStr
*/
public M_RealData(String queryStr) {
System.out.println("开始根据queryStr处理数据,这个过程可能会比较耗时");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("数据处理完成,赋值result");
result = "处理完成的数据";
}
@Override
public String getQueryResult() {
return result;
}
}
下面外部调用未来客户端
package thread_demo_01;
/**
* @Author: yesiming
* @Platform: Mac
* @Date: 4:32 PM 2019/10/10
*/
public class M_Main {
public static void main(String[] args) {
M_FutureClient client = new M_FutureClient();
M_Data data = client.query("asdfasd");
System.out.println("这里可以做别的事儿了。。。");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("返回数据是:" + data.getQueryResult());
}
}
好,结束