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();
  }
 
//取结果
    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); 
//等待一段时间
        
        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("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);
//将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){}
     }