Future模式有点类似于商品订单。比如在网购时,当看中某一个商品时,就可以提交订单,当订单处理完成后,在家里等待商品送货上门即可。或者说更形象的我们发送Ajax请求的时候,页面是异步的进行后台处理,用户无需一直等待请求的结果,可继续浏览或操作其他内容。
下面看一个例子:
1.客户端发送请求
客户端发送请求,包装类返回“假”的结果,同时创建一个线程去执行真实的操作。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//假设这里在计算一个结果要花5秒钟,我们就可以起一个线程让他计算,在计算期间我们可以干别的事情。
Callable<Integer> call = new Callable<Integer>() {
public Integer call() throws Exception {
System.out.println("正在计算结果");
Thread.sleep(5000);
return 1;
};
};
//把call交给FutureTask
FutureTask<Integer> task = new FutureTask<>(call);
//开启线程去执行计算任务
Thread t = new Thread(task);
t.start();
//在这期间,我们可以干点别的
Thread.sleep(10);
System.out.println("干点别的");
//干完之后,等计算完成,在爱拿到结果
Integer result = task.get();
System.out.println("拿到的结果为:"+result);
}
}
下面,我们模拟一个场景,实现Future模式。 假设,现在你要去面包店去买一块蛋糕,但是,生产一块蛋糕要花一段时间,你总不能一直等下去,这个时候,你可以先去上班,等下班回来之后,你再去取蛋糕。 我们就实现这么一个场景:
public class FutureClient {
public Data request(final String queryStr){
//1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情
final FutureData futureData = new FutureData();
//2 启动一个新的线程,去加载真实的数据,传递给这个代理对象
new Thread(new Runnable() {
public void run() {
//3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象
RealData realData = new RealData(queryStr);
futureData.setRealData(realData);
}
}).start();
return futureData;
}
}
2.包装类操作
package com.thread.mythread.conn015;
public interface Data {
String getRequest();
}
public class FutureData implements Data{
private RealData realData ;
private boolean isReady = false;
public synchronized void setRealData(RealData realData) {
//如果已经装载完毕了,就直接返回
if(isReady){
return;
}
//如果没装载,进行装载真实对象
this.realData = realData;
isReady = true;
//进行通知
notify();
}
public synchronized String getRequest() {
//如果没装载好 程序就一直处于阻塞状态
while(!isReady){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//装载好直接获取数据即可
return this.realData.getRequest();
}
}
3.真实结果
public class RealData implements Data{
private String result ;
public RealData (String queryStr){
System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作..");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("操作完毕,获取结果");
result = "查询结果";
}
public String getRequest() {
return result;
}
}
4、执行测试
package com.thread.mythread.conn015;
public class Main {
public static void main(String[] args) throws InterruptedException {
FutureClient fc = new FutureClient();
Data data = fc.request("请求参数");
System.out.println("请求发送成功!");
System.out.println("做其他的事情...");
String result = data.getRequest();
System.out.println(result);
}
}
5、打印结果
请求发送成功!
做其他的事情…
根据请求参数进行查询,这是一个很耗时的操作..
操作完毕,获取结果
查询结果