Future模式

  • Future模式简介

  Future模式有点相似于网上购物,在你购买商品,订单生效以后,你能够去作本身的事情,等待商家经过快递给你送货上门。Future模式就是,当某一程序提交请求,指望获得一个答复。可是可能服务器程序对这个请求的处理比较慢,所以不可能立刻收到答复。可是,在传统的单线程环境下,调用函数是同步的,它必须等到服务程序返回结果,才能继续进行其余处理。而Future模式下,调用方法是异步的,本来等待返回的时间段,在主调函数中,则能够处理其余的任务。传统的串行程序钓友以下图所示:服务器

  

  Future模式的处理流程:并发

  从图中能够看出,虽然call()自己是一个须要很长世间处理的程序。可是,服务程序不等数据处理完就马上返回客户端一个伪数据(相似于商品订单,你购物须要的是商品自己),实现Future模式的客户端在拿到这个返回结果后,并不急于对它进行处理,而是去调用其它的业务逻辑,使call()方法有充分的时间去处理完成,这也是Future模式的精髓所在。在处理完其余业务逻辑后,最后再使用处理比较费时的Future数据。这个在处理过程当中,就不存在无谓的等待,充分利用了时间,从而提高了系统的响应和性能。app

  • Future模式的核心结构

  下面以一个经典的Future实现为例,简单介绍下Future的核心实现。代码中Date接口:返回数据的接口;FutureDate类:实现Date接口,构造很快,返回一个虚拟的伪数据,须要装配RealDate;RealDate类:实现Date接口,返回真实数据,构造比较慢;Client:返回Date数据,当即返回FutureDate数据,并开启线程装配RealDate数据。异步

  代码实现:ide

 1 public interface Data {
 2     public String getResult();
 3 }
 4 
 5 public class FutureData implements Data {
 6     
 7     protected RealData realData = null;
 8     
 9     protected boolean isReady = false;
10     //进行同步控制
11     public synchronized void setResult(RealData realData){
12         if(isReady){
13             return;
14         }
15         System.out.println("FutureData.setResult()");
16         this.realData=realData;
17         isReady = true;
18         notifyAll();
19         
20     } 
21     //实际调用返回RealDate的数据
22     @Override
23     public synchronized String getResult() {
24         while(!isReady){
25             try {
26                 wait();
27             } catch (InterruptedException e) {
28                 e.printStackTrace();
29             }
30         }
31         System.out.println("FutureData.getResult()");
32         return realData.result;
33     }
34 
35 public class RealData implements Data{
36     
37     protected final String result;
38     
39     public RealData(String s) {
40         StringBuffer sb = new StringBuffer();
41         
42         for (int i = 0; i < 10; i++) {
43             sb.append(s);
44             try {
45                 //模拟构造时间比较长
46                 Thread.sleep(1000);
47             } catch (InterruptedException e) {
48                 
49             }
50             
51         }
52         
53         System.out.println("RealData.RealData()");
54         result = sb.toString();
55     }
56 
57 public class Client {
58     public Data request(final String queryStr){
59                 //返回伪数据
60         final FutureData futureData = new FutureData();
61                 //开启线程构造真实数据
62         new Thread(){
63             public void run(){
64                 RealData realData = new RealData(queryStr);
65                 futureData.setResult(realData);
66             }
67         }.start();
68                 //返回伪数据,等待真实数据加载
69         return futureData;
70     }
71 }    

  启动系统,调用Client发送请求:函数

1 public class TestMain {
2     public static void main(String[] args) {
3         Data data = new Client().request("123456");
4         System.out.println(data);
5         System.out.println(data.getResult());
6     }
7 }

  能够看出,FutureDate是Future模式实现的关键,它实际是真实数据RealDate的代理,封装了获取RealDate的等待过程。性能

  • JDK内置实现

  在JDK的内置并发包中,就已经内置了一种Future的实现,提供了更加丰富的线程控制,其基本用意和核心理念与上面实现代码一致。this

  在JDK中的Future模式中,最重要的是FutureTask类,它实现了Runnable接口,能够做为单独的线程运行。在其run()方法中,经过Sync内部类,调用Callable接口,并维护Callable接口的返回对象。当使用FutureTask.get()时,将返回Callable接口的返回对象。FutureTask还能够对任务自己进行其余控制操做。spa

  利用Callable接口实现上述例子相同的操做:线程

  RealDate类的实现:

 1 public class Real1Data implements Callable<String>{
 2     
 3     private String reaString;
 4     
 5     public Real1Data(String reaString) {
 6         super();
 7         this.reaString = reaString;
 8     }
 9 
10   
11     @Override
12     public String call() throws Exception {
13         
14         StringBuffer sb = new StringBuffer();
15         
16         for (int i = 0; i < 10; i++) {
17             sb.append(reaString);
18             try {
19                 Thread.sleep(100);
20             } catch (InterruptedException e) {
21                 // TODO: handle exception
22             }
23             
24         }
25         
26         return sb.toString();
27     }
28 
29 }

  Client代码实现:

 1 public class Test1Main {
 2     public static void main(String[] args) throws InterruptedException, ExecutionException {
 3         FutureTask<String> future =  new FutureTask<>(new Real1Data("1111"));
 4         
 5         ExecutorService exe = Executors.newFixedThreadPool(1);
 6         
 7         exe.submit(future);
 8         
 9         System.out.println("FutureTask");
10         
11         try {
12             Thread.sleep(1000);
13         } catch (InterruptedException e) {
14             // TODO Auto-generated catch block
15             e.printStackTrace();
16         }
17         
18         System.out.println("FutureTask"+future.get());
19     }
20 }    

  能够看出RealDate的构造速度很快,其核心代码逻辑放在了call()中实现,再也不须要Date和FutureDate,直接经过RealDate来构造FutureTask,将其做为单独的线程运行。在提交请求后,执行其余业务逻辑,作好经过FututeTask.get()方法,获得RealDate的执行结果。

  Futute模式核心在于去除了主调用函数的等待时间,并使得本来须要等待的时间能够充分利用来处理其余业务逻辑,充分的利用了系统资源。

相关文章
相关标签/搜索