Future模式是多线程开发中常见的设计模式,它的核心思想是异步调用。对于Future模式来说,它无法立即返回你需要的数据,但是它会返回一个契约,将来你可以凭借这个契约去获取你需要的信息。
- 传统的同步方法
调用一段耗时的程序。当客户端发出call请求,这个请求需要很长的一段时间才会返回,客户端一直在等待直到数据返回随后再进行其他任务的处理。 - Future模式
客户端在得到这个返回结果后并不急于对其进行处理而是调用其他业务逻辑,充分利用等待时间,在完成其他业务处理后,再使用返回比较慢的Future数据。这样在整个调用中就不存在无谓的等待,充分利用所有的时间片,从而提高了系统响应速度。
1. Future模式的核心角色
Funture模式 使用代理模式,在FutureData里持有了 RealData 对象。 Data、RealData、FutureData 共同组成代理模式。
1.1 定义Data接口
public interface Data {
String get();
}
1.2 定义RealData
RealData的构造花费很多时间。是真实的结果数据。
public class RealData implements Data {
private String result;
public RealData(String request) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = "这是你的货";
}
public String get() {
return result;
}
}
1.3 定义FutureData
FutureData持有RealData,当客户端调用get()方法时,会阻塞等待。那它阻塞等待什么呢?
等待ready信号。当服务端完成了数据的获取计算,就会调用setResult(RealData realData)
方法,此时会将realdata设入,并设置isReady为真,唤醒get()方法。
public class FutureData implements Data {
protected RealData realData = null;
protected boolean isReady = false;
// 进行同步控制
public synchronized void setResult(RealData realData) {
if (isReady) {
return;
}
this.realData = realData;
isReady = true;
notifyAll();
}
// 实际调用返回RealData的数据
@Override
public synchronized String get() {
while (!isReady) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return realData.get();
}
}
1.4 服务端程序
服务端程序在接收请求后,立即启动一个新线程去取货,并交付futureData给客户端。
public class Server {
public Data request(final String request) {
final FutureData futureData = new FutureData();
new Thread(new Runnable() {
public void run() {
RealData realData = new RealData(request);
futureData.setResult(realData);
}
}).start();
return futureData;
}
}
1.5 示例
public class Main {
public static void main(String[] args) {
Server server= new Server();
Data data = server.request("给我一箱货");
//这里客户端可以做很多其他的运算,不浪费时间。
dosomething_log();
dosomething_db();
//去拿货了
String result = data.get();
System.out.println(result);
}
}
总结
Future 模式是一种异步方法。可以合理安排分配时间,考虑许多IO任务,在等待的时候可以充分利用CPU。Future 模式 将调用与执行分离。
JDK中JUC的Callable Future FutureTask 即 使用了Future 模式。 可以参考 《JAVA多线程进阶篇 10、JUC线程池之Callable Future FutureTask》
多线程系列在github上有一个开源项目,主要是本系列博客的实验代码。
https://github.com/forestnlp/concurrentlab
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。