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();
}
}
来源:oschina
链接:https://my.oschina.net/u/729281/blog/668793