zoukankan      html  css  js  c++  java
  • java线程学习之Future模式

                  Future模式的核心是异步调用。它类似于我们商品订单。像我们在网上买了个手机,当我们购买成功后,会生成此订单,此订单信息就是将来取商品的重要凭证,商品无法立即拿到要通过物流寄过来。在此期间,我们就可以接着我们自己的事,等待收货即可。它同时也像我们的Ajax请求的时候,页面是异步的进行后台处理。用户无需等待请求结果,可以继续浏览操作或操作其他内容。

    Future模型时序图:

      

                                                      Future模式的主要参与者

    参与者 作用
    Main 系统启动,调用Client发出请求
    Host 返回Data对象,并立即返回FutureData,并开启ClientThread线程装配RealData
    Data 表示访问数据的接口。由FutureData和RealData实现该接口
    FutureData Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData
    RealData 真实数据,构造函数的处理需要花费很长时间

    Future模型的类图

                

           看第一个类Main

    public class Main {
    
        public static void main(String[] args) throws InterruptedException {
            
            FutureClient fc = new FutureClient();   //先创建Client端的实例
            Data data = fc.request("请求参数");//为这个实例装载数据,此时返回的data数据。request相当于是购买商品成功,data相当于订单信息
            System.out.println("请求发送成功!");
            System.out.println("做其他的事情...");
            
            String result = data.getRequest();//调用之前收到的返回值data的getRequest()方法获取真正的结果,相当于拿着之前的订单信息去取快递
            System.out.println(result);
            
        }
    }

          在这个类中,会先创建Client实例,将要处理的任务交给Client端去处理,这是立刻收到数据,但此时的是FutureData,而不是RealData。然后自己接着做的事情,最后调用之前收到的返回值data的getRequest()方法获取真正的结果(即之前request方法的处理结果)

      第二个 Host(Client端)类

     1 public class FutureClient {
     2 
     3     public Data request(final String queryStr){
     4         //1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情
     5         final FutureData futureData = new FutureData();
     6         //2 启动一个新的线程,去加载真实的数据,传递给这个代理对象
     7         new Thread(new Runnable() {
     8             @Override
     9             public void run() {
    10                 //3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象
    11                 RealData realData = new RealData(queryStr);
    12                 futureData.setRealData(realData);
    13             }
    14         }).start();
    15         
    16         return futureData;
    17     }
    18     
    19 }

     在这类中会先创建FutureData的实例(futureData)。将这个实例作为返回值返回给调用者。然后会创建一个新的线程并在新线程中创建RealData的实例(realData)。虽然创建RealData的实例需要花费很长时间,但是因为这个实例是在新线程中进行的,并不会影响Main类的处理。当realData创建成功后,线程会调用setRealData()方法,将其放置到futureData中。由于创建RealData会花费一些时间,所以设置futureData字段就是未来的事情了。

    第三个Data接口

    1 public interface Data {
    2 
    3     String getRequest();
    4 
    5 }

    Data接口是表示数据访问(getContent()方法)的接口

    第四个Future类:

     1 public class FutureData implements Data{
     2 
     3     private RealData realData ;
     4     
     5     private boolean isReady = false;
     6     
     7     public synchronized void setRealData(RealData realData) {
     8         //如果已经装载完毕了,就直接返回
     9         if(isReady){
    10             return;
    11         }
    12         //如果没装载,进行装载真实对象
    13         this.realData = realData;
    14         isReady = true;
    15         //进行通知
    16         notify();
    17     }
    18     
    19     @Override
    20     public synchronized String getRequest() {
    21         //如果没装载好 程序就一直处于阻塞状态
    22         while(!isReady){
    23             try {
    24                 wait();
    25             } catch (InterruptedException e) {
    26                 e.printStackTrace();
    27             }
    28         }
    29         //装载好直接获取数据即可
    30         return this.realData.getRequest();
    31     }
    32 
    33 
    34 }

    realData字段是用于保存稍后创建完毕的RealData实例的字段,可以通过setRealData方法设置该字段。

    ready字段表示是否已经为realData赋值的字段。如果它为true,表示已经为realData赋值。

    第五个RealData类

     1 public class RealData implements Data{
     2 
     3     private String result ;
     4     
     5     public RealData (String queryStr){
     6         System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作..");
     7         try {
     8             Thread.sleep(5000);
     9         } catch (InterruptedException e) {
    10             e.printStackTrace();
    11         }
    12         System.out.println("操作完毕,获取结果");
    13         result = "查询结果";
    14     }
    15     
    16     @Override
    17     public String getRequest() {
    18         return result;
    19     }
    20 
    21 }
    生于忧患,死于安乐
  • 相关阅读:
    GlusterFS + lagstash + elasticsearch + kibana 3 + redis日志收集存储系统部署 01
    Python输出字符串或文件颜色显示
    系统维护常用脚本
    免密码登录服务器python脚本
    python 常用模块之ConfigParser
    Robot Framework -004 为了进行Web测试,安装SeleniumLibrary外部库
    Robot Framework -005 测试SeleniumLibrary外部库,添加一个测试web用例
    Robot Framework -003 在Windows10 安装Eclipse作为编辑器,安装 RED 插件。
    Robot Framework -002 在Windows10上的安装
    Robot Framework -001 简介
  • 原文地址:https://www.cnblogs.com/songlove/p/10845969.html
Copyright © 2011-2022 走看看