一挤牛、定義
guarded是“被保護著的”泥张、“被防衛(wèi)著的”意思呵恢,suspension則是“暫停”的意思圾结。當(dāng)現(xiàn)在并不適合馬上執(zhí)行某個操作時瑰剃,就要求想要執(zhí)行該操作的線程等待齿诉,這就是Guarded Suspension Pattern筝野。
Guarded Suspension Pattern 會要求線程等候晌姚,以保障實例的安全性,其它類似的稱呼還有g(shù)uarded wait歇竟、spin lock等挥唠。
二、模式案例
下面的案例是一種簡單的消息處理模型焕议,客戶端線程發(fā)起請求宝磨,有請求隊列緩存請求,然后發(fā)送給服務(wù)端線程進行處理盅安。
Request類:
//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 + " ]";
}
}
客戶端線程類:
//客戶端線程不斷生成請求唤锉,插入請求隊列
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) {
}
}
}
}
服務(wù)端線程類:
//客戶端線程不斷從請求隊列中獲取請求,然后處理請求
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)窿祥。
執(zhí)行:
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();
}
}
三、模式講解
角色:
Guarded Suspension Pattern 的角色如下:
- GuardedObject (被防衛(wèi)的對象)參與者
GuardedObject 參與者是一個擁有被防衛(wèi)的方法(guardedMethod)的類蝙寨。當(dāng)線程執(zhí)行g(shù)uardedMethod時晒衩,只要滿足警戒條件,就能繼續(xù)執(zhí)行墙歪,否則線程會進入wait set區(qū)等待听系。警戒條件是否成立隨著GuardedObject的狀態(tài)而變化。
GuardedObject 參與者除了guardedMethod外虹菲,可能還有用來更改實例狀態(tài)的的方法stateChangingMethod靠胜。
在Java語言中,是使用while語句和wait方法來實現(xiàn)guardedMethod的届惋;使用notify/notifyAll方法實現(xiàn)stateChangingMethod髓帽。如案例中的RequestQueue 類。
注意:Guarded Suspension Pattern 需要使用while脑豹,這樣可以使從wait set被喚醒的線程在繼續(xù)向下執(zhí)行前檢查Guard條件郑藏。如果改用if,當(dāng)多個線程被喚醒時瘩欺,由于wait是繼續(xù)向下執(zhí)行的必盖,可能會出現(xiàn)問題。