一、什么是Future模型
常见的多线程设计模式有:单例模式、不变模式、生产者-消费者模式、Future模式;而这里介绍Future模式,它的核心思想就是异步调用。当我们需要调用一个函数,但是这个函数执行很慢,如果我们不需要马上知道结果,我们可以立即返回,让它在后台慢慢处理这个请求,对于调用者来说,可以先处理一些其他任务,这个就充分利用等待时间,在真正需要数据场合再去尝试获取需要的数据。
二、Future模式的主要角色
主要参与者如表:
参与者 | 作用 |
---|---|
Main | 启动系统,调用Client发出请求 |
Client | 返回Data对象,理解返回FutureData,并开启ClientThread线程装配RealData |
Data | 返回数据的接口 |
FutureData | Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData |
RealData | 真实数据,构造比较慢 |
核心结构
三、Future模式的简单实现
实现中有一个核心接口就是Data,这是客户端希望获取的数据,这个Data接口有两个重要的实现,分别是RealData,也就是真实数据,这就是我们最终需要获取的信息,还有一个FutureData,它用来提取RealData的一个“订单”因此FutureData可以立即获得
Data接口
public interface Data {
public String getResult();
}
实现类FutureData
这个是Future模式的关键,实际上是真实数据RealData的代理,封装了获取RealData的等待过程
public class FutureData implements Data{
protected RealData realdata=null;//FutureData是RealData的包装
protected boolean isReady=false;
public synchronized void setRealData(RealData realdata){
if(isReady){
return;
}
this.realdata=realdata;
isReady=true;
notifyAll();//RealData已经被注入,通知getResult()
}
@Override
public synchronized String getResult() { //会等待RealData构造完成
// TODO Auto-generated method stub
while(!isReady){
try {
wait(); //一直等待,知道RealData被注入
} catch (Exception e) {
// TODO: handle exception
}
}
return realdata.result;
}
}
FutureData实现了一个快速返回的RealData包装,所以它只是一个包装,没有真实数据,在里面的getResult()方法如果实际数据没有准备好就等待,直到RealData准备好并注入FutureData才返回数据
实现类RealData
public class RealData implements Data {
protected final String result;// protected可访问同包的元素
public RealData(String para) {
// RealData的构造可能很慢,需要用户等待好久,这里使用sleep模拟
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 10; i++) {
sb.append(para);
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
}
result = sb.toString();
}
@Override
public String getResult() {
// TODO Auto-generated method stub
return result;
}
}
Client
在客户端程序,创建获取FutureData,并开启构造RealData的线程,立即返回FutureData
public class Client {
public Data request(final String queryStr){
final FutureData future=new FutureData();//实现获取FutureData
new Thread(){
public void run(){ //RealData的构造很慢,所以在单独的线程中进行
RealData realdata=new RealData(queryStr);
future.setRealData(realdata);
}
}.start();
return future;//FutureData会被立即返回
}
}
主函数
负责调用Client发起请求 ,并消费返回的数据
public static void main(String[] args) {
Client client=new Client();
//这里会立即返回,因为得到FutureData,而不是RealData
Data data=client.request("name");
System.out.println("请求完毕");
try {
//这里可以用一个sleep代替对其他业务逻辑的处理
//在处理这些业务逻辑中,RealData被创建,从而充分利用了等待时间
Thread.sleep(2000);
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("数据="+data.getResult());
}
参考:《Java高并发程序设计》