Java多線程基礎(五)——Guarded Suspension模式

1、定義

guarded是「被保護着的」、「被防衛着的」意思,suspension則是「暫停」的意思。當如今並不適合立刻執行某個操做時,就要求想要執行該操做的線程等待,這就是Guarded Suspension Pattern。
Guarded Suspension Pattern 會要求線程等候,以保障實例的安全性,其它相似的稱呼還有guarded wait、spin lock等。緩存

2、模式案例

下面的案例是一種簡單的消息處理模型,客戶端線程發起請求,有請求隊列緩存請求,而後發送給服務端線程進行處理。安全

Request類:dom

//request類表示請求
public class Request {
    private final String name;
    public Request(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public String toString() {
        return "[ Request " + name + " ]";
    }
}

客戶端線程類:this

//客戶端線程不斷生成請求,插入請求隊列
public class ClientThread extends Thread {
    private Random random;
    private RequestQueue requestQueue;
    public ClientThread(RequestQueue requestQueue, String name, long seed) {
        super(name);
        this.requestQueue = requestQueue;
        this.random = new Random(seed);
    }
    public void run() {
        for (int i = 0; i < 10000; i++) {
            Request request = new Request("No." + i);
            System.out.println(Thread.currentThread().getName() + " requests " + request);
            requestQueue.putRequest(request);
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
            }
        }
    }
}

服務端線程類:spa

//客戶端線程不斷從請求隊列中獲取請求,而後處理請求
public class ServerThread extends Thread {
    private Random random;
    private RequestQueue requestQueue;
    public ServerThread(RequestQueue requestQueue, String name, long seed) {
        super(name);
        this.requestQueue = requestQueue;
        this.random = new Random(seed);
    }
    public void run() {
        for (int i = 0; i < 10000; i++) {
            Request request = requestQueue.getRequest();
            System.out.println(Thread.currentThread().getName() + " handles  " + request);
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
            }
        }
    }
}

請求隊列類:線程

public class RequestQueue {
    private final LinkedList<Request> queue = new LinkedList<Request>();
    public synchronized Request getRequest() {
        while (queue.size() <= 0) {
            try {                                   
                wait();
            } catch (InterruptedException e) {      
            }                                       
        }                                           
        return (Request)queue.removeFirst();
    }
    public synchronized void putRequest(Request request) {
        queue.addLast(request);
        notifyAll();
    }
}

注:getRequest方法中有一個判斷while (queue.size() <= 0),該判斷稱爲Guarded Suspension Pattern 的警惕條件(guard condition)。code

執行:對象

public class Main {
    public static void main(String[] args) {
        RequestQueue requestQueue = new RequestQueue();
        new ClientThread(requestQueue, "Alice", 3141592L).start();
        new ServerThread(requestQueue, "Bobby", 6535897L).start();
    }
}

3、模式講解

角色:
Guarded Suspension Pattern 的角色以下:blog

  • GuardedObject (被防衛的對象)參與者

GuardedObject 參與者是一個擁有被防衛的方法(guardedMethod)的類。當線程執行guardedMethod時,只要知足警惕條件,就能繼續執行,不然線程會進入wait set區等待。警惕條件是否成立隨着GuardedObject的狀態而變化。
GuardedObject 參與者除了guardedMethod外,可能還有用來更改實例狀態的的方法stateChangingMethod。隊列

在Java語言中,是使用while語句和wait方法來實現guardedMethod的;使用notify/notifyAll方法實現stateChangingMethod。如案例中的RequestQueue 類。

注意:Guarded Suspension Pattern 須要使用while,這樣能夠使從wait set被喚醒的線程在繼續向下執行前檢查Guard條件。若是改用if,當多個線程被喚醒時,因爲wait是繼續向下執行的,可能會出現問題。

相關文章
相關標籤/搜索