• Future 模式简介


    简介

    Future 模式是多线程开发中的一种常见设计模式,它的核心思想是异步调用。

    比如我们在网上购物,付款后就会产生一个订单,之后你该干嘛干嘛,快递小哥会上门送货,而不必像在超市结账那样,付款后要等着收银员打出小票再帮你打包商品,这个时间你只能站那等着。

    总的来说,Future 模式无法立即给出你想要的结果,但它会给你一个契约,之后你可以随时通过这个契约来获取你想要的结果。

    例子

    下边举个简单的例子:

    例子中,Data 接口有两个实现类,RealData 表示真实的数据也就是最终想要的,FutureData 表示一个契约,通过这个 FutureData 可以获得 RealData 的真实数据。

    FutureData:

     1 package com.zhengbin.springboot.future;
     2 
     3 /**
     4  * Created by zhengbin on 2017/11/14
     5  */
     6 public class FutureData implements Data {
     7     private RealData realData = null;
     8     private boolean isReady = false;
     9 
    10     public synchronized void setRealData(RealData realData) {
    11         if (isReady) {
    12             return;
    13         }
    14         this.realData = realData;
    15         isReady = true;
    16         notifyAll();
    17     }
    18 
    19     @Override
    20     public synchronized String getResult() {
    21         while (!isReady) {
    22             try {
    23                 wait();
    24             } catch (InterruptedException e) {
    25             }
    26         }
    27         return realData.getResult();
    28     }
    29 }

    FutureData 相当于 RealData 的代理(契约),封装了获取 RealData 等待的过程。

    调用 getRealData 方法时,如果数据还没有准备好,线程就会等待(阻塞),当执行 setRealData 后,将会唤醒所有等待(阻塞)中的线程,这时才能获取到数据。

    RealData:

     1 package com.zhengbin.springboot.future;
     2 
     3 /**
     4  * Created by zhengbin on 2017/11/14
     5  */
     6 public class RealData {
     7     private final String result;
     8 
     9     public RealData(String param) {
    10         StringBuffer sb = new StringBuffer();
    11         for (int i = 0;i < 10;i++) {
    12             sb.append(param);
    13             try {
    14                 Thread.sleep(300);
    15             } catch (InterruptedException e) {
    16             }
    17         }
    18         result = sb.toString();
    19     }
    20 
    21     public String getResult() {
    22         return result;
    23     }
    24 }

    RealData 的构造函数,模拟了一个数据构成很慢的过程。

    Client:

     1 package com.zhengbin.springboot.future;
     2 
     3 /**
     4  * Created by zhengbin on 2017/11/14
     5  */
     6 public class Client {
     7     public Data request(final String requestStr) {
     8         final FutureData futureData = new FutureData();
     9         new Thread() {
    10             @Override
    11             public void run() {
    12                 RealData realData = new RealData(requestStr);
    13                 futureData.setRealData(realData);
    14             }
    15         }.start();
    16         return futureData;
    17     }
    18 }

    Client 就是我们调用的客户端,实现了获取 FutureData,并开启构造 RealData 的线程,该线程单独执行,主线程直接返回,只不过返回的是一个契约也就是 FutureData,真正的数据 RealData 则在另一个单独的线程中缓慢的构造,构造完成后就会通过 FutureData 的 setRealData 将真实数据保存,这样客户端就可以 get 到真实数据了。

    FutureTest:

     1 package com.zhengbin.springboot.future;
     2 
     3 /**
     4  * Created by zhengbin on 2017/11/14
     5  */
     6 public class FutureTest {
     7     public static void main(String[] args) throws InterruptedException {
     8         Client client = new Client();
     9         Data futureData = client.request("zhengbin");
    10         System.out.println("request done...");
    11         Thread.sleep(500);
    12         System.out.println("other done...");
    13         System.out.println("result : "+futureData.getResult());
    14     }
    15 }

    测试方法通过 Client 发起调用,调用后模拟执行其他的逻辑,耗费 0.5 秒,之后需要用到 Data 的数据了,但构造真实数据的时间需要 3 秒,此时主线程就会阻塞在这里,等待真实数据的构造完成。

    这种方式就给了主线程去执行其他任务的时间,节省了 0.5 秒的时间,可以用来去做别的事情。

    参考资料

    [1] 实战 Java 高并发程序设计 5.5

  • 相关阅读:
    使用eclipse新建一个SWT工程
    C++类的构造函数
    D3D编程的常见报错及解决
    D3D窗口的初始化
    C++联合体的内存使用
    QT程序如何编译
    Restart
    HTML
    信号、槽位及布局
    QT对话框程序
  • 原文地址:https://www.cnblogs.com/zhengbin/p/8324587.html
Copyright © 2020-2023  润新知