什么是Future模式?
Future模式是多线程开发中一种经典的设计模式,其核心思想是异步调用 。它通过将耗时操作 与主线程 分离,让主线程不必等待结果返回 即可继续执行其他任务,从而显著提升系统的响应速度 和资源利用率。
同步调用
异步调用

实现了Future模式的客户端在拿到这个返回结果后,并不急于处理,⽽是调⽤了其他业务逻辑,充分利⽤了等待时间,这就是Future模式的核心所在。在完成了其他业务逻辑的处理后,再使⽤返回⽐较慢的Future数据。
Future模式的主要参与者包括:
- Main :系统入口,调用
Client发起请求,处理其他业务,最终通过Future获取真实结果 - Client :接收请求后,立即返回
FutureData,同时启动独立线程异步构建RealData - Data :结果返回接口,定义获取真实结果的方法(如
getResult()) - FutureData :虚拟结果实现类,封装
RealData的构建等待逻辑,是Future模式的核心代理 - RealData :真实结果实现类,构造过程耗时(如数据计算、IO操作),最终通过
getResult()返回
Future模式的简单实现
核心接口Data
Data就是客户端希望获取的数据,在Future模式中,Data接口有两个重要的实现:
RealData:最终获取的真实数据FutureData:用于提取RealData
java
public interface Data<T> {
public T getResult();
}
实现类FutureData
FutureData实现了一个可以快速返回的RealData包装,它只是一个虚拟实现,因此很快就可以返回。当使用FutureData的getResult方法的时候,如果实际的数据还没有准备好,就会被阻塞,等待RealData准备好并注入FutureData中才最终返回。
java
public class FutureData<T> implements Data<T> {
protected RealData<T> realData; //FutureData是RealData的包装
protected boolean isReady;
@Override
public synchronized T getResult() {
while(!isReady){
try{
this.wait(); //数据还没准备好,线程阻塞,直到被唤醒
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return realData.getResult();//返回真实数据
}
public synchronized void setRealData(RealData realData) {
if (isReady){
return ;
}
this.realData=realData;
this.isReady=true;
this.notifyAll(); //RealData已经被注入,唤醒所有的阻塞线程
}
}
实现类RealData
RealData是真实的数据,是最终需要使用的数据模型,它的构造非常慢。
java
public class RealData<T> implements Data<T> {
private T data;
public RealData(T data) throws InterruptedException {
for (int i=0;i<10;i++){//使用循环睡眠来代替耗时操作
System.out.println("正在构造数据...");
TimeUnit.SECONDS.sleep(1);
}
this.data=data;
}
@Override
public T getResult() {
return data;
}
}
客户端程序
Client实现了获取FutureData并开启构造RealData的线程。接收请求之后,会直接返回一个FutureData。
java
public class Client {
public Data<String> request(){
final FutureData futureData=new FutureData();
new Thread(()->{
RealData<String> realData=new RealData<>("hello,world");
futureData.setRealData(realData);
}).start();
return futureData;
}
}
主函数Main
ini
public static void main(String[] args) throws InterruptedException {
Client client = new Client();
Data<String> request = client.request();
for(int i=0;i<5;i++){
System.out.println("处理其他事情中...");
TimeUnit.SECONDS.sleep(1);
}
System.out.println(request.getResult());
System.out.println("整个程序已结束");
}
以下是程序输出的结果:

JDK中的Future模式
Future接口就类似之前的FutureData是用来立即返回的对象,通过get()可以获取到真实的数据。
RunnableFuture继承了Runnable与Future接口,其中run方法用于线程构建真实的数据。
FutureTask是RunnableFuture的一个具体实现类,其内部有一个内部类Sync,Sync最终会调用Callble接口,完成实际数据的组装。
Callable接口调用call方法来返回需要构造的实际数据。
实际案例
实现一个RealData实现Callable接口。
csharp
public class RealData implements Callable<String> {
@Override
public String call() throws Exception {
for (int i=0;i<10;i++){//使用循环睡眠来代替耗时操作
System.out.println("正在构造数据...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return "hello,world";
}
}
Callable接口的call方法会构造真实的数据,并返回。
java
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<String> future=new FutureTask<>(new RealData());
ExecutorService executorService = Executors.newFixedThreadPool(1);
//执行FutureTask相当于之前调用Client
//内部开启线程执行call方法
executorService.execute(future);
System.out.println("请求完毕");
for(int i=0;i<5;i++){
System.out.println("做其他业务逻辑中...");
TimeUnit.SECONDS.sleep(1);
}
System.out.println("数据="+future.get());
System.out.println("程序执行完毕");
}