Java多線程ActiveObject模式

概述

接受異步消息的主動對象。
Java的java.lang.Thread類的實例就是一種主動對象。
主動對象可以從外部接收和處理異步消息并根據需要返回處理結果翠订。
Active Object模式中的主動對象會通過自己特有的線程在合適的時機處理從外部接收到的異步消息摩骨。
Active Object模式有時也稱Actor模式驳规。

示例程序

 使用的類
 - Main   測試程序行為的類
 - MakerClientThread   發(fā)出“生成字符串”請求的線程
 - DisplayClientThread  發(fā)出“顯示字符串”請求的線程
 - ActiveObject  定義“主動對象”的接口(API)的接口
 - ActiveObjectFactory  創(chuàng)建“主動對象”的類
 - Proxy   將方法調用轉換為MethodRequest對象的類(實現(xiàn)了ActiveObject的接口)
 - SchedulerThread  調用execute 方法處理 MethodRequest 對象的類
 - ActivationQueue  按順序保存MethodRequest對象的類
 - MethodRequest  表示請求的抽象類
 - MakeStringRequest  makeString方法(生成字符串)對應的類秉沼。MethodRequest類的子類
 - DisplayStringRequest  displayString方法(顯示字符串)對應的類州刽。MethodRequest類的子類
 - Result   表示執(zhí)行結果的抽象類
 - FutureResult  在Future 模式中表示執(zhí)行結果的類
 - RealResult  表示實際的執(zhí)行結果的類
 - Servant      執(zhí)行實際處理的類(實現(xiàn)了ActiveObject接口)

Main 類

import activeobject.ActiveObject;
import activeobject.ActiveObjectFactory;

public class Main {
  public static void main(String[] args) {
    ActiveObject activeObject = ActiveObjectFactory.createActiveObject();
    new MakerClientThread("Alice", activeObject).start();
    new MakerClientThread("Bobby", activeObject).start();
    new DisplayClientThread("Chris", acvtiveObject).start();  
  }
}

MakerClientThread 類

import  activeobject.ActiveObject;
import  activeobject.Result;

public class MakerClientThread extends Thread {
  private final ActiveObject activeObject;
  private final char fillchar;
  public MakerClientThread(String name, ActiveObject activeObject){
    super(name);
    this.activeObject = activeObject;
    this.fillchar = name.charAt(0);
  }
  public void run(){
    try {
      for(int i = 0; true; i++){
        Result<String> result = activeObject.makeString(i, fillchar);
        Thread.sleep(10);
        String value = result.getResultValue();
        System.out.println(Thread.currentThread().getName() + ":  value = " + value);

      }
    } catch (InterruptedException e){}
  }
}

DisplayClientThread 類

import activeobject.ActiveObject;
import activeobject.Result;

public class DisplayClientThread extends Thread {
  private final ActiveObject activeObject;
  public DisplayClientThread(String name, ActiveObject activeObject){
    super(name);
    this.activeObject = activeObject;
  }
  public void run() {
    try {
      for( int i = 0; true; i++){
        String string = Thread.currentThread().getName() + "  " + i;
        activeObject.displayString(string);
        Thread.sleep(200);
      }
    } catch(InterruptedException e) {} 
  }
}

ActiveObject 接口

package activeobject;

public interface ActiveObject {
  public abstract Result<String> makeString (int count, char fillchar);
  public abstract void displayString(String string);
}

ActiveObjectFactory 類

package activeobject;

public class ActiveObjectFactory {
  public static ActiveObject createActiveObject() {
    Servant servant = new Servant();
    ActivationQueue queue = new ActivationQueue();
    SchedulerThread scheduler = new SchedulerThread(queue);
    Proxy proxy = new Proxy(scheduler, servant);
    scheduler.start();
    return proxy;
  }
}

Proxy 類

package activeobject;

class Proxy implements ActiveObject {
  private final SchedulerThread scheduler;
  private final Servant servant;
  public Proxy(SchedulerThread scheduler, Servant servant) {
    this.scheduler = scheduler;
    this.servant = servant;
  }
  public  Result<String> makeString(int count, char fillchar){
    FutureResult<String> future = new FutureResult<String>();
    scheduler.invoke(new MakeStringRequest<servant, future, count, fillchar));
    return future;
  }
  public void displayString(String string){
    scheduler.invoke(new DisplayStringRequest(servant, string));
  }
}

ScheduelrThread 類

package activeobject;

class SchedulerThread extends Thread {
  private final ActivationQueue  queue;
  private SchedulerThread(ActivationQueue queue){
    this.queue = queue;
  }
  public void invoke(MethodRequest request){
    queue.putRequest(request);
  }
  public void run(){
    while (true) {
      MethodRequest request = queue.takeRequest();
      request.execute();
    }
  }
}

ActivationQueue 類

package activeobject;

class ActivationQueue {
  private static final int MAX_METHOD_REQUEST  = 100;
  private final MethodRequest[]  requestQueue;
  private int tail;
  private int head;
  private int count;

  public ActivationQueue(){
    this.requestQueue = new MethodRequest[MAX_METHOD_REQUEST];
    this.head = 0;
    this.tail = 0;
    this.count = 0;
  }
  public synchronized void putRequest(MethodRequest request){
    while(count >= requestQueue.length){
       try{
        wait();
      } catch (InterruptedException e) {} 
     }

    requestQueue[tail] = request;
    tail = (tail + 1) % requestQueue.length;
    count++;
    notifyAll();
  }
  public synchronized MethodRequest takeRequest() {
    while (count <= 0 ){
        try{
          wait();
        } catch (InterruptedException e){}
     }
     MethodRequest request = requestQueue[head];
     head = (head + 1) % requestQueue.length;
     count--;
     notifyAll();
     return request;
  }
}

主動對象方 MethodRequest類`

package activeobject;

abstract class MethodRequest<T> {
  protected final Servant servant;
  protected final FutureResult<T> future;
  protected MethodRequest(Servant servant, FutureResult<T> future){
    this.servant = servant;
    this.future = future;
  }

  public abstract void execute():
}

主動對象方 MakeStringRequest 類

package activeobject;

class MakeStringRequest extends MethodRequest<String> {
  private final int count;
  private final char fillchar;
  public MakeStringRequest(Servant servant, FutureResult<String> future, int Count, char fillchar) {
    super(servant, future);
    this.count = count;
    this.fillchar = fillchar;
  }

  public void execute() {
    Result<String> result = servant.makeString(Count, fillchar);
    future.setResult(result);
  }
}

主動對象方 DisplayStringRequest 類

package activeobject;

class DisplayStringRequest extends MethodRequest<Object> {
  private final String string;
  public DisplayStringRequest(Servant servant, String string){
    super(servant, null);
    this.string =string;
  }


public void execute() {
  servant.displayString(string);
}
}

主動對象方 Result 類

package activeobject;

public abstract class Result<T> {
  public abstract T getResultValue();
}

主動對象方 FutureResult 類

package activeobject;

class FutureResult<T>  extends Result<T> {
  private Result<T> result;
  private boolean ready = false;
  public synchronized void setResult(Result<T> result) {
    this.result = result;
    this.ready = true;
    notifyAll();
  }

  public synchronized T getResultValue() {
    while ( !ready ) {
      try {
        wait();
      } catch (InterruptedException e) {}
    }

    return result.getResultValue();
  }
}

主動對象方 Servant 類

package activeobject;

class Servant implements ActiveObject {
  public Result<String> makeString(int count ,  char fillchar) {
    char[] buffer = new char[Count];
     for (int i = 0 ; i < count; i++) {
       buffer[i] = fillchar;
       try { Thread.sleep(100); } catch (InterruptedException e) {}
     }
     return new RealResult<String>(new String(buffer));
  } 
  public void displayString(String string){
    try {
      System.out.print("displayString: " + string);
    } catch(InterruptedException e) {}
  }
}

ActiveObject 模式中的角色

  • Client(委托者)
    Client角色調用ActiveObject對象的方法來委托處理呕寝,它能夠調用的只有ActiveObject 角色提供的方法勋眯。調用這些方法后,程序控制權會立即返回下梢。
  • ActiveObject(主動對象)
    ActiveObject對象定義了主動對象向Client角色提供的接口(API)客蹋。
  • Proxy(代理人)
    Proxy角色負責將方法調用轉換為MethodRequest角色的對象。轉換后的MethodReques角色會傳遞給Scheduler角色孽江。
  • Scheduler
    Scheduler角色負責將Proxy角色傳遞來的MethodRequest角色傳遞給ActivationQueue角色讶坯,以及從ActivationQueue角色取出并執(zhí)行MethodRequest角色這兩項工作。
  • MethodRequest
    MethodRequest角色是與來自Client角色的請求對應的角色岗屏。MethodRequest定義了負責執(zhí)行處理的Servant角色辆琅,以及負責設置返回值的Future角色和負責執(zhí)行請求的方法(execute)。
  • ConcreteMethodRequest
    ConcreteMethodRequest角色是使用MethodRequest角色與具體的方法相對應的角色这刷。
  • Servant(仆人)
    Servant角色負責實際地處理請求婉烟。
    調用Servant角色的是Scheduler角色的線程。Scheduler角色會從ActivationQueue角色取出一個MethodRequest角色并執(zhí)行它暇屋。此時似袁,Scheduler角色調用的是Servant角色的方法。
    Servant角色實現(xiàn)了ActiveObject角色定義的接口(API)咐刨。
    Proxy角色會將請求轉換為MethodRequest角色昙衅,而Servant角色則會實際地執(zhí)行該請求。Scheduler角色介于Proxy角色和Servant角色之間定鸟,負責管理按照什么順序執(zhí)行請求而涉。
  • ActivationQueue(主動隊列)
    ActivationQueue 角色是保存MethodRequest角色的類。
    調用putRequest方法的是Client角色的線程联予,而調用takeRequest方法的是Scheduler角色的線程啼县。這里使用了Producer-Consumer模式材原。

  • VirtualResult(虛擬結果)
    VirtualResult角色與Future角色、RealResult角色共同構成了Future模式谭羔。
    Client角色在獲取處理結果時會調用VirtualResult角色的getResultValue方法华糖。

  • Future(期貨)
    Future角色時Client角色在獲取處理結果時實時調用的角色麦向。當處理結果還沒出來的時候瘟裸,它會使用Guarded Suspension模式讓Client角色的線程等待結果出來。

  • RealResult(真實結果)
    RealResult角色是表示處理結果的角色诵竭。Servant角色會創(chuàng)建一個RealResult角色作為處理結果话告。然后調用Future角色的setRealResult方法將其設置到Future角色中。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末卵慰,一起剝皮案震驚了整個濱河市沙郭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裳朋,老刑警劉巖病线,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鲤嫡,居然都是意外死亡送挑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門暖眼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惕耕,“玉大人,你說我怎么就攤上這事诫肠∷九欤” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵栋豫,是天一觀的道長挤安。 經常有香客問我,道長丧鸯,這世上最難降的妖魔是什么蛤铜? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮骡送,結果婚禮上昂羡,老公的妹妹穿的比我還像新娘。我一直安慰自己摔踱,他們只是感情好虐先,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著派敷,像睡著了一般蛹批。 火紅的嫁衣襯著肌膚如雪撰洗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天腐芍,我揣著相機與錄音差导,去河邊找鬼。 笑死猪勇,一個胖子當著我的面吹牛设褐,可吹牛的內容都是我干的。 我是一名探鬼主播泣刹,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼助析,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了椅您?” 一聲冷哼從身側響起外冀,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掀泳,沒想到半個月后雪隧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡员舵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年脑沿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片固灵。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡捅伤,死狀恐怖,靈堂內的尸體忽然破棺而出巫玻,到底是詐尸還是另有隱情丛忆,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布仍秤,位于F島的核電站熄诡,受9級特大地震影響,放射性物質發(fā)生泄漏诗力。R本人自食惡果不足惜凰浮,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望苇本。 院中可真熱鬧袜茧,春花似錦、人聲如沸瓣窄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俺夕。三九已至裳凸,卻和暖如春贱鄙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姨谷。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工逗宁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梦湘。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓瞎颗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親践叠。 傳聞我的和親對象是個殘疾皇子言缤,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,090評論 1 32
  • 國家電網公司企業(yè)標準(Q/GDW)- 面向對象的用電信息數(shù)據交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,913評論 6 13
  • 進程和線程 進程 所有運行中的任務通常對應一個進程,當一個程序進入內存運行時,即變成一個進程.進程是處于運行過程中...
    勝浩_ae28閱讀 5,087評論 0 23
  • 接著上節(jié) condition_varible 嚼蚀,本節(jié)主要介紹future的內容禁灼,練習代碼地址。本文參考http:/...
    jorion閱讀 14,776評論 1 5
  • 最近開始練習瑜伽守谓,這是在每天帶娃、讀書您单、碼字斋荞、健步走的忙碌生活中再擠出點兒時間用來提升自己。老公為了配合我虐秦,...
    f409d6ef4875閱讀 633評論 0 0