您的位置:首页 > 编程语言

并发编程-Future模式

2016-05-02 17:57 393 查看
1.Future模式有点类似商品订单。比如在网上进行购物,当看中某一件商品时,就可以提交订单。提交订单完毕在家等候送货上门。卖家根据订单取货、发货,并配送到顾客手中。大部分情况下,卖家处理订单没那么快,可能需要几天时间。而这段时间买家不必再家里等候,可以做其他事情。

将此类推到程序设计中,当某一段程序提交了一个请求,期望得到一个答复。但非常不幸的是,服务程序对这个请求的处理可能非常慢。在传统的单线程环境下,调用函数是同步的,也就是说它必须要等到服务程序返回结果后,才能够进行其他处理。而在Future模式下,调用方式该为异步,而原来等待返回的时间段,在主调用函数中,则可以用于处理其他事物。传统程序的调用流程如下图所示。



图1-1 传统串行程序调用流程

采用Future模式设计程序,调用流程如下。



图1-2 Future模式流程图

表1-3 Future模式的主要参与者

参与者 作用
Main 系统启动,调用Client发出请求你
Client 返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData
Data 返回数据的接口
Future Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData
RealData 真实数据,其构造是比较慢的
2.Future模式的代码实现
2.1Main函数的实现

main函数主要负责调用Client发起请求,并使用返回的数据:

public static void main(String[] args) {
// TODO Auto-generated method stub

Client client = new Client();
Data data = client.request("test");
System.out.println("----------------------------------");

try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("----------------------------------");
System.out.println(data.getResult());

}

2.2Client的实现

public class Client {

public Data request(final String req_name) {

FutureData fd = new FutureData();

new Thread() {
@Override
public void run() {
// TODO Auto-generated method stub

RealData rd = new RealData(req_name);
fd.setRd(rd);

};
}.start();

return fd;

}
}

2.3Data的实现

public interface Data {

public String getResult();

}

2.4FutureData的实现

FutureData实现了一个快速返回的RealData的包装。是RealData的虚拟实现,因此它可以快速的被构造返回。当使用FutureData的getResult()方法时,程序会阻塞,等待RealData被注入到程序中,才使用RealData的getResult()方法返回。

/**
* packed the readdata
* @author cosco
*
*/
public class FutureData implements Data {

protected RealData rd = null;

protected volatile boolean  isReady  = false;

public RealData getRd() {
return rd;
}

public synchronized void setRd(RealData rd) {

if(isReady){
return;
}

this.rd = rd;

isReady = true;

notifyAll();

}

@Override
public synchronized String getResult() {
// TODO Auto-generated method stub
while(!isReady){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

return rd.getResult();
}

}


2.5RealData的实现

RealData是最终需要使用的数据模型,它的构造很慢。在这里,使用sleep()函数模拟这个过程:


package org.cosco.thread;

/**
*
* @author cosco
*
*/
public class RealData implements Data {

private final String result;

public RealData(String param){
StringBuffer sb = new StringBuffer();
for(int i = 0; i < 10; i++){
sb.append(param);

try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

result = sb.toString();
}

@Override
public  String getResult() {
// TODO Auto-generated method stub

return result;
}

}


3.JDK的内置实现

Future模式比较常用,JDK的并发包中,就已经了一中Future模式的实现。JDK中实现的比较复杂,提供了更为丰富的多线程控制功能。核心结构如图:



图3-1 JDK内置的Future模式

可以使用JDK内置的Future模式实现我们的功能,首先实现Callable接口,实现具体的业务逻辑。

import java.util.concurrent.Callable;

public class RealData implements Callable<String>{

private String param;

public RealData(String param){
this.param = param;
}

@Override
public String call() throws Exception {
// TODO Auto-generated method stub

StringBuffer sb = new StringBuffer();

for(int i = 0; i < 10; i++){
sb.append(param);

Thread.sleep(100);

}
return sb.toString();
}

}

在这改进中,RealData的构造变得非常快,其业务逻辑被移到call()方法内,并通过call()方法返回。

main方法修改如下:

package testthread02;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class testmain {

public static void main(String[] args) throws InterruptedException, ExecutionException {

FutureTask<String> future = new FutureTask<String>(new RealData("a"));

ExecutorService es = Executors.newFixedThreadPool(1);

es.submit(future);

try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println(future.get());

es.shutdown();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息