Future 模式的核心思想就是异步调用。
当你请求一个耗时的接口时,可以不用一直阻塞在这个请求上,而是做个标识,继续做其它的事情。在之后需要用到数据的时候,再来用这个标识获取这个接口返回的数据。
简单实现
基本思路是用一个新的线程来获取这个耗时的数据。
定义一个获取数据的接口。
public interface Data {
public String getResult();
}
模拟真实数据
- 在构造函数中
sleep 1
秒,模拟这是一个耗时的接口
public class RealData implements Data{
protected final String result;
public RealData(String data) {
try {
// 表示这个数据的构建是个耗时的过程
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = "Result:" + data;
}
@Override
public String getResult() {
return result;
}
}
FutrueData
- 提供一个
isReady
来检测数据是否已经准备完毕
public class FutureData implements Data{
protected RealData realData = null;
private Boolean isReady = false;
public synchronized void setRealData(RealData realData) {
if (isReady)
return;
this.realData = realData;
isReady = true;
notifyAll();
}
public String getResult() {
while (!isReady) {
try {
wait();
} catch (InterruptedException e) {
}
}
return realData.getResult();
}
public Boolean isReady() {
return isReady;
}
}
Client
通过一个新的线程
去获取这个耗时的数据。
public class Client {
public FutureData request(final String query) {
FutureData futureData = new FutureData();
new Thread(){
@Override
public void run() {
RealData realData = new RealData(query);
futureData.setRealData(realData);
}
}.start();
return futureData;
}
}
Main
public class Main {
public static void main(String[] args) {
Client client = new Client();
FutureData data = client.request("weather");
System.out.println("程序不会阻塞,中间可以做别的事");
while (!data.isReady()) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("睡眠 500 ms");
}
System.out.println(data.getResult());
}
}
运行结果
JDK 中的 Future 使用
jdk 中已经实现了一套完成的 future 模式。
public class RealData implements Callable<String> {
private String para;
public RealData(String para) {
this.para = para;
}
@Override
public String call() throws Exception {
Thread.sleep(1000);
return "Result:" + para;
}
}
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> task = new FutureTask<>(new RealData("weather"));
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(task);
System.out.println("请求完毕,可以做其它事情");
while (!task.isDone()) {
Thread.sleep(500);
System.out.println("sleep 500ms");
}
System.out.println(task.get());
}
}