zoukankan      html  css  js  c++  java
  • Java多线程异步调度程序分析(二)

    源自:http://blog.sina.com.cn/s/blog_4cc16fc50100c0uh.html

    public abstract class Result {   //抽象的结果类

      public abstract Object getResultValue();

    }

     

    class FutureResult extends Result{  //取货凭证类

      private Result result;

      private boolean completed;

     

      public synchronized void setResult(Result result){  //存放真实的结果

        this.result = result;

        this.completed = true;

        this.notifyAll();

      }

     

      public synchronized Object getResultValue(){ //取结果

        while(!this.completed){

          try{

            this.wait();

          }catch(Throwable t){}

        }

        // 调用RealResult类的getResultValue返回真实结果

        return this.result.getResultValue();  

      }

    }

     

    class RealResult extends Result{ //表示真实结果的抽象类

      private final Object resultValue;

       public RealResult(Object resultValue){

        this.resultValue = resultValue;

      }

      public Object getResultValue(){

        return this.resultValue;

      }

    }

    现在这个异步消息处理器已经有了模型,这个异步处理器包括如下对象

        Servant             忠心做真实的事务

        ActivationQueue     将请求缓存起来以便调度

        Scheduler           对容器中的请求根据一定原则进行调度执行

        Proxy               将特定方法请求转换为特定对象

        所有这些都是这个异步处理器的核心部件,既然是核心部件,我们就要进行封装而不能随便让调用者来修改,所以我们用工厂模式来产生处理器Axman对象

    public class AxmanFactory {

      public static Axman createAxman() {

        Servant s = new Servant(); //创建实际处理请求的对象

        ActivationQueue queue = new ActivationQueue(); //创建存放请求的队列

        Scheduler st = new Scheduler(queue); //创建调度策略对象

        Proxy p = new Proxy(st,s); //创建代理对象

        st.start(); //启动调度策略线程Scheduler

        return p;  //返回代理对象

      }

    }

     

    用两个请求的产生者不停产生请求

     

    public class ResultInvokeThread extends Thread{

    // ResultInvokeThread线程发送需要有返回值的请求

      private final Axman ao;

      private final char c;

      public ResultInvokeThread(String name,Axman ao){

        this.ao = ao;

        this.c = name.charAt(0);

      }

     

      public void run(){

        try{

          int i = 0;

          while(true){

     //调用Proxy的ruseultTest方法向队列中添加一个请求,返回取货凭证FutureResult

            Result result  = this.ao.resultTest(i++,c); 

            Thread.sleep(10); //等待一段时间

            

            String value = (String)result.getResultValue();

          System.out.println(Thread.currentThread().getName() + " value = " + value);

          }

        }

        catch(Throwable t){}

      }

    }

     public class NoResultInvokeThread extends Thread{

         //NoResultInvokeThread发送不需要返回值的请求

      private final Axman ao;

      public NoResultInvokeThread(String name,Axman ao){

        super(name);

        this.ao = ao;

      }

       public void run(){

        try{

          int i = 0;

          while(true){

            String s = Thread.currentThread().getName() + i++;

            ao.noResultTest(s);

            Thread.sleep(20);

          }

        }

        catch(Throwable t){}

      }

    }

    // 调用程序的主类

    public class Program {

      public static void main(String[] args) {

        //创建代理对象,同时启动调度策略线程Scheduler。

        Axman ao = AxmanFactory.createAxman();

        new ResultInvokeThread("Axman",ao).start(); //启动需要返回值的请求线程

        new ResultInvokeThread("Sager",ao).start();

        new NoResultInvokeThread("Macke",ao).start();//启动不需要返回值的请求线程

      }

    }

     

    1. Scheduler线程运行后,从队列ActivationQueue中取出请求,调用不同请求类型相应的execute方法。

     

       如果请求类型为ResultRequest,ResultRequest的execute方法首先调用Servant的resultTest方法,处理请求(请求处理完成后,返回处理结果RealResult对象);然后调用FutureResult的setResult方法存储结果。

     

    ResultRequest的execute方法

     

       public void execute(){

         //创建Result对象,获取的是RealResult对象。

         Result result = servant.resultTest(this.count,this.c);

         this.future.setResult(result); //将RealResult对象存储。

       }

     

    Servant的resultTest方法

     

       public Result resultTest(int count,char c){

         char[] buf = new char[count];

         for(int i = 0;i < count;i++){

           buf[i] = c;

           try{

             Thread.sleep(100);

           }catch(Throwable t){}

         }

        //调用RealResult的构造方法,返回RealResult对象。

          return new RealResult(new String(buf));    

    }

     

    FutureResult的setResult方法

     

       public synchronized void setResult(Result result){

         this.result = result;

         this.completed = true;

         this.notifyAll();

       }

     

    2. ResultInvokeThread线程运行后,调用Proxy的ruseultTest方法。

     

       resultTest方法创建取货凭证对象FutureResult,然后调用scheduler的invoke方法(invoke方法调用ActivationQueue队列的putRequest方法,向队列中添加请求。),然后返回取货凭证对象。

      请求线程调用sleep()等待一段时间。

      ResultInvokeThread线程继续调用Result的getResultValue对象,读取执行结果。

     

    3. 程序中有两处需要同步

     

       一是读取与存储请求,这涉及到ActivationQueue队列的getRequest方法和putRequest方法。

        Scheduler线程、ResultInvokeThread线程、NoResultInvokeThread线程会同时对这些方法进行访问

     

       二是读取与存储结果,这涉及到FutureResult的getResultValue方法与setResult方法。

       Scheduler线程、ResultInvokeThread线程、NoResultInvokeThread线程会同时对这些方法进行访问。

       每个请求对应一个请求结果,请求A获取的是请求结果A,不会得到请求结果B。

     

       FutureResult的getResultValue方法声明如下

     

       public synchronized Object getResultValue(){

         while(!this.completed){

           try{

             this.wait();

           }catch(Throwable t){}

         }

     

  • 相关阅读:
    SpringCloud
    SpringCloud
    一个表的字段更新另一个表的字段
    MYSQL5.7 sql_mode=only_full_group_by
    CentOS7 防火墙操作
    log4j DailyRollingFileAppender, DatePattern 配置
    Fiddler抓包-会话框添加查看get与post请求类型选项
    Fiddler抓包-工具介绍(request和response)
    Fiddler抓包-get与post请求
    Fiddler抓包-只抓APP的请求
  • 原文地址:https://www.cnblogs.com/fangyuan303687320/p/5305303.html
Copyright © 2011-2022 走看看