1. 程式人生 > >多執行緒設計模式——Guarded Suspension(保護性暫掛模式)

多執行緒設計模式——Guarded Suspension(保護性暫掛模式)

這些都是根據我最近看的《Java實戰指南多執行緒程式設計(設計模式篇)》所得整理。

模式名稱

Guarded Suspension(保護性暫掛模式)

模式面對的問題

多執行緒程式設計中,往往將一個任務分解為不同的部分,將其交由不同的執行緒來執行,這些執行緒相互協作的時候,會出現一個執行緒等待另一個執行緒一定操作過後才能進行的情景,這個時候就需要這個執行緒退出執行。

解決方法

有一個類GuardedObject包含受保護方法的物件,存放被保護物件的方法和被保護物件的喚醒方法。一個類GuardedAction抽象目標動作,並關聯了目標動作鎖需的保護條件.一個ConcreteGuardedAction應用程式鎖體現的具體目標動作及其關聯的保護條件,一個Predicate抽象保護條件,ConCretePredicate應用程式鎖實現的具體保護條件,Blocker負責執行受保護的方法所線上程的掛起和喚醒。並執行ConcreteGuardedAction鎖執行的目標操作。ConditionVarBlocker給予Java條件變數實現的Blocker.

例子程式碼

這也是書上的程式碼,需求是:某系統有個告警功能模組,改模組的主要功能是將其接收到的告警資訊傳送給告警伺服器。
AlarmAgent類

public class ALarmAgent {
    //用於記錄AlarmAgent
    private volatile boolean connectedToServer = false;
    //模式角色:GuardedSuspension.Predicate
    private final Predicate agentConnected = new Predicate(){
        @Override
        public
boolean evaluate(){ return connectedToServer; } }; //模式角色GuaededSuspension.Blocker private final Blocker blocker = new ConditionVarBlocker(); //心跳定時器 private final Timer heartbeatTimer = new Timer(true); //傳送告警資訊 public void sendAlarm(final AlarmInfo alarm) throws
Exception { GuardedAction<Void> guardedAction = new GuardedAction<Void>(agentConnected){ public Void call()throws Exception{ doSendAlarm(alarm); return null; } }; blocker.callWithGuard(guardedAction); } //通過網路連結講告警資訊傳送給告警伺服器 private void doSendAlarm(AlarmInfo alarm){ //省略其他與設計模式無關的程式碼 Debug.info("sending alarm"+alarm); //模擬傳送告警值伺服器的耗時 try{ Thread.sleep(50); }catch(Exception e){ } } public void init(){ //省略其他與設計模式無關的程式碼 //告警伺服器連線執行緒 Thread connectingThread = new Thread(new ConnectingTask()); connectingThread.start(); heartbeatTimer.schedule(new HeartbeatTask(), 60000,2000); } public void disconnect(){ //省略其他與設計模式無關的程式碼 Debug.info("disconnected from alarm server."); connectedToServer = false; } protected void onConnected(){ try{ blocker.singalAfter(new Callable<Boolean>(){ @Override public Boolean call(){ connectedToServer = true; Debug.info("connnected to server"); return Boolean.TRUE; } }); }catch(Exception e){ e.printStackTrace(); } } protected void onDisconnected(){ connectedToServer = false; } //負責與告警伺服器建立網路連結 private class ConnectingTask implements Runnable{ @Override public void run(){ //省略其他與設計模式無關的程式碼 //模擬連線操作耗時 try{ Thread.sleep(100); }catch(InterruptedException e){ ; } } } //心跳定時任務:定時檢車與該井伺服器的連結是否正常,發現連結異常後自動重新連結 private class HeartbeatTask extends TimerTask{ @Override public void run(){ //省略其他與設計模式無關的程式碼 if(!testConnection()){ onDisconnected(); reconnect(); } } private boolean testConnection(){ //省略其他與設計模式無關的程式碼 return true; } private void reconnect(){ ConnectingTask connectingThread = new ConnectingTask(); //直接在心跳定時器執行緒中執行 connectingThread.run(); } } }

暫掛的sendAlarm

public interface Predicate {
    boolean evaluate();
}

public abstract class GuardedAction<V> implements Callable<V>{
    protected final Predicate guard;
    public GuardedAction(Predicate guard){
        this.guard = guard;
    }
}

public interface Blocker {
    //在保護條件城裡時執行目標動作;否則阻塞當前執行緒,知道保護條件成立
    <V> V callWithGuard(GuardedAction<V>guardedAction) throws Exception;
    //執行 stateOperation所制定的操作後,決定是否喚醒本Blocker
    void signalAfter(Callable<Boolean>stateOperation) throws Exception;
    void signal() throws InterruptedException;
    //執行stateOperation所制定的操作後,決定是否喚醒本Blocker
    void broadcastAfter(Callable<Boolean> stateOperation) throws Exception;
}

public class ConditionVarBlocker implements Blocker{
    private final Lock lock;

    private final Condition condition;

    public ConditionVarBlocker(Lock lock){
        this.lock = lock;
        this.condition = lock.newCondition();
    }

    public ConditionVarBlocker(){
        this.lock = new ReentrantLock();
        this.condition = lock.newCondition();
    }

    public <V> V callWithGuard(GuardedAction<V> guardedAction) throws Exception {
        lock.lockInterruptibly();
        V result;
        try{
            final Predicate guard = guardedAction.guard;
            while(!guard.evaluate()){
                condition.await();
            }
            result = guardedAction.call();
            return result;
        }finally{
            lock.unlock();
        }
    }

    public void broadcastAfter(Callable<Boolean> stateOperation)
            throws Exception {
        lock.lockInterruptibly();
        try{
            if(stateOperation.call()){
                condition.signal();
            }
        }finally{
            lock.unlock();
        }
    }



    public void signal() throws InterruptedException {
        lock.lockInterruptibly();
        try{
            condition.signal();
            }finally{
                lock.unlock();
        }
    }

    public void signalAfter(Callable<Boolean> stateOperation) throws Exception {
        lock.lockInterruptibly();
        try{
            if(stateOperation.call()){
                condition.signalAll();
            }
        }finally{
            lock.unlock();
        }

    }
}

需要關注的問題

  1. 記憶體可見性和鎖洩露
  2. 執行緒被過早喚醒
  3. 巢狀監視器鎖死
  4. 可能增加JVM垃圾回收的負擔

相關推薦

執行設計模式——Guarded Suspension保護性模式

這些都是根據我最近看的《Java實戰指南多執行緒程式設計(設計模式篇)》所得整理。 模式名稱 Guarded Suspension(保護性暫掛模式) 模式面對的問題 多執行緒程式設計中,往往將一個任務分解為不同的部分,將其交由不同的執行緒來執行,這些

《Java執行程式設計實戰》——第4章 Guarded Suspension保護性模式

一個執行緒等待另一個執行緒完成一定的操作,才能繼續執行。 核心思想是如果某個執行緒執行特定的操作前需要滿足一定的條件,則在該條件未滿足時將該執行緒暫停執行(waiting)。 類圖 如果頻繁出現保護方法被呼叫時保護條件不成立,那麼保護方法的執行執行緒就會頻繁地被暫掛和喚醒,而導致頻繁

執行的那點兒事之自旋鎖

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】    自旋鎖是SMP中經常使用到的一個鎖。所謂的smp,就是對稱多處理器的意思。在工業用的pcb板上面,特別是伺服器上面,一個pcb板有多個cpu是很正常的事情。這些c

關於執行的幾點總結部落格園遷移

 關於執行緒 synchronized關鍵字:  不能用在變數和建構函式上  放在方法上面,鎖定的是物件,放在靜態方法上鎖定的是類  不應該鎖定常量,比如String等型別因為程式中這個物件難免還會用

執行的那點兒事之無鎖鏈表

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】     前面,為了使得寫操作快速進行,我們定義了順序鎖。但是順序鎖有個缺點,那就是處理的資料不能是指標,否則可能會導致exception。那麼有沒有辦法使得處理的資料

java執行設計模式Guarded Suspension

想象一個場景,你在排隊領軍訓的裝備,當你排隊到視窗的時候,工作人員對你說,等一下,讓我叫後勤先去倉庫取下裝備再給你,於是你等到工作人員取回裝備才能領走裝備。 抽象為一個java程式模型:你是一個執行緒

Java 執行設計模式Guarded Suspension

Guarded Suspension 模式核心是一個受保護的方法(Guarded Method)。該方法執行其所要真正執行的操作時需要滿足特定的條件(Predicate, 保護條件)。類似與 wait/notify, 當條件不滿足時,執行受保護的執行緒會被掛起進

java執行設計模式 -- 流水線模式Pipeline

十一、流水線模式(Pipeline) 1、核心思想 將一個任務處理分解為若干個處理階段,其中每個處理階段的輸出作為下一個處理階段的輸入,並且各個處理階段都有相應的工作者執行緒去執行相應的計算。 2、評價: 充分利用CPU,提高其計算效率。

執行設計模式:第六篇 - ThreadLocal和Active Object模式

一,ThreadLocal         Java 中的 ThreadLocal 類給多執行緒程式設計提供了一種可以讓每個執行緒具有自己獨立空間的機制,在這個空間記憶體儲的資料是執行緒特有的,不對外共享。  &nb

執行設計模式:第四篇 - Thread-Per-Message模式和Worker-Thread模式

一,Thread-Per-Message模式         Thread-Per-Message模式是說為每個請求都分配一個執行緒,由這個執行緒來執行處理。這裡包含兩個角色,請求的提交執行緒和請求的執行執行緒。  

執行設計模式:第三篇 - 生產者-消費者模式和讀寫鎖模式

一,生產者-消費者模式         生產者-消費者模式是比較常見的一種模式,當生產者和消費者都只有一個的時候,這種模式也被稱為 Pipe模式,即管道模式。      &nb

14.執行設計模式 - Master-Worker模式

多執行緒設計模式 - Master-Worker模式  併發設計模式屬於設計優化的一部分,它對於一些常用的多執行緒結構的總結和抽象。與序列相比並行程式結構通常較為複雜,因此合理的使用並行模式在多執行緒併發中更具有意義。 1. Master-Worker模式 - Master-Worker

13.執行設計模式 - Future模式

多執行緒設計模式 - Future模式 併發設計模式屬於設計優化的一部分,它對於一些常用的多執行緒結構的總結和抽象。與序列相比並行程式結構通常較為複雜,因此合理的使用並行模式在多執行緒併發中更具有意義。 1. Future   Future模式是多執行緒開發中非常常見的一種設計模式,它的

執行設計模式:Master-Worker模式

Master-Worker是常用的平行計算模式。它的核心思想是系統由兩類程序協作工作:Master程序和Worker程序。Master負責接收和分配任務,Worker負責處理子任務。當各個Worker子程序處理完成後,會將結果返回給Master,由Master作歸納總結。其好處就是能將一個大任務分解

執行設計linux c pthread_mutex_trylock和pthread_mutex_lock

1.問題:理想情況下有兩條執行緒,一條執行緒不斷插入佇列,一條執行緒不斷取出佇列,兩條執行緒是併發執行的,但實驗階段的現象卻是第一條執行緒全部插入佇列後第二條執行緒才會開始取 (1)執行緒一: pt

Java 執行設計模式之基礎概念

順序、併發與並行 順序 用於表示多個操作“依次處理”。比如把十個操作交給一個人來處理時,這個人要一個一個地按順序來處理 並行 用於標識多個操作“同時處理”。比如十個操作分給兩個人處理時,這兩個人就會並行來處理。 併發 相對於順序和並行來說比較抽象,用於表示“將一個

圖解java執行設計模式

序章1 Java執行緒 何謂執行緒 文中給出的解釋是:正在執行程式的主體 執行緒的啟動 新執行緒的啟動一定是呼叫start()方法,該方法主要是執行兩步操作 啟動新執行緒 呼叫新執行緒的run()方法 這裡需要注意: public class Test(

圖解java執行設計模式-第二章 Immutable模式

以下內容是我在閱讀《圖解Java多執行緒設計模式》一書中的總結和思考 本章配圖文字是:想破壞也破壞不了。 定義 例項物件的內部狀態不會發生變化,也就是說不提供對外改變屬性的方法(除了建立物件時初始化的方法外),那麼這個類就是Immutable的,無需任何互斥操作都可

執行設計模式Future、Master-Worker和生產者-消費者模型

並行設計模式屬於設計優化的一部分,它是對一些常用的多執行緒結構的總結和抽象。與序列結構相比,並行程式的結構通常更為複雜。因此合理的使用並行模式在多執行緒開發中更具有意義,在這裡主要介紹Future、Master-Worker和生產者-消費者模型。Future模式Future模

Java執行設計模式執行模式

前序:   Thread-Per-Message Pattern,是一種對於每個命令或請求,都分配一個執行緒,由這個執行緒執行工作。它將“委託訊息的一端”和“執行訊息的一端”用兩個不同的執行緒來實現。該執行緒模式主要包括三個部分:   1,Request參