1.Future模式有点相似商品订单。好比在网上进行购物,当看中某一件商品时,就能够提交订单。提交订单完毕在家等候送货上门。卖家根据订单取货、发货,并配送到顾客手中。大部分状况下,卖家处理订单没那么快,可能须要几天时间。而这段时间买家没必要再家里等候,能够作其余事情。 java
将此类推到程序设计中,当某一段程序提交了一个请求,指望获得一个答复。但很是不幸的是,服务程序对这个请求的处理可能很是慢。在传统的单线程环境下,调用函数是同步的,也就是说它必需要等到服务程序返回结果后,才可以进行其余处理。而在Future模式下,调用方式该为异步,而原来等待返回的时间段,在主调用函数中,则能够用于处理其余事物。传统程序的调用流程以下图所示。 多线程
图1-1 传统串行程序调用流程 并发
采用Future模式设计程序,调用流程以下。 app
图1-2 Future模式流程图 异步
表1-3 Future模式的主要参与者 ide
参与者 | 做用 |
Main | 系统启动,调用Client发出请求你 |
Client | 返回Data对象,当即返回FutureData,并开启ClientThread线程装配RealData |
Data | 返回数据的接口 |
Future | Future数据,构造很快,可是是一个虚拟的数据,须要装配RealData |
RealData | 真实数据,其构造是比较慢的 |
2.1Main函数的实现 函数
main函数主要负责调用Client发起请求,并使用返回的数据: this
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的实现 spa
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(); } }