定义
Future模式有点类似商品订单。比如说在网上进行购物,当你买了一件物品时,你就只需要在家里等待商品或者在此之间做其他的事情。将此类型推到程序中,当某一段程序提交了一个请求,期望得到一个答复。但非常不幸的是,服务程序的处理可能很慢。在传统单线程的环境下,调用函数是同步的,也就是说必须等到服务程序处理完后才能进行其他的操作。而在Future模式下,调用方式改为异步,而原先等待返回的时间段,在主调用函数中国,则可用于调用其他的事务。如图1所示,显示了一段传统程序调用的流程。
图一
根据图一可以很清楚的看出传统穿串行程序的缺点。而使用Future模式替换原来的实现方式,可以改进其调用过程。如图二所示
图二
图二显示了一个广义的Future模式的实现,从Data中我们可以看,获取数据需要很长一段时间。但是服务程序不等数据处理完成直接返回一个伪造数据,实现了Future模式的客户端拿到这个返回结果,并不急于对其进行处理,而去调用其他业务逻辑。充分的利用了时间,这就是Future模式的核心部分。等到其他业务处理完后,最后在使用返回比较慢的数据。
实现
参与者
| 作用 |
Main | 系统主程序,调用Client发送请求 |
Client | 发送请求,返回Data对象。并开启ClientThread线程配置RealData |
Data | 数据接口。 |
FutureData | 虚拟数据,实现Data接口,构造快,要对RealData进行装配 |
RealData | 真实数据。实现Data接口,构造缓慢。 |
参与者结构图
代码实现
主程序类
class FutureTest
{
public static void main(String []args){
Client cli = new Client();
Data data = cli.request("zhangsan");
try{
Thread.sleep(2000);
}catch(Exception e){
}
System.out.println(data.getResult());
}
}
数据接口
interface Data
{
public String getResult();
}
客户请求类
class Client
{
public Data request(final String name){
final FutureData fd = new FutureData();
new Thread(){
public void run(){
RealData rd = new RealData(name);
fd.setData(rd);
}
}.start();
return fd;
}
}
伪数据类
class FutureData implements Data
{
private RealData real;
private boolean isReady = false;
public synchronized void setData(RealData real){
if(isReady){
return ;
}
this.real = real;
this.isReady = true;
notifyAll();
}
public synchronized String getResult(){
while(!isReady){
try{
wait();
}catch(Exception e){
}
}
return real.getResult();
}
}
真实数据类
class RealData implements Data
{
private StringBuffer sb ;
public RealData(String name){
sb = new StringBuffer();
for(int i = 0 ; i < 10 ; i++){
sb.append(name);
try{
Thread.sleep(200);
}catch(Exception e){
}
}
}
public String getResult(){
return sb.toString();
}
}
JDK的内置实现
Future模式时非常常用的,所以在jdk的并发包中就内置了一种Future模式的实现。与上述的自实现相比,JDK中的实现是相当复杂的,并且提供了更为丰富的线程控制功能,但其中的基本用意和核心功能是一样的。
JDK中的核心结构如图