今天來介紹 Guarded Suspension 模式,它的主要目的是當條件沒有成立時會進行一直循環的等待,等待條件成立時才會進行通知繼續來執行。主要的使用情境在 Client 和 Server 連線時,如果 Server 沒有接收到 Client 的 Request 時,Server 就會一直進行等待的動作,等到有 Client 的 Request 時 Server 才會進行執行的動作。
Guarded Suspension 模式和前幾天介紹的 Balking 模式主要的差異地方在於,如果條件不成立時 Guarded Suspension 會一直進行等待執行的動作 (wait),Baling 模式是條件不成立時不會進行等待和執行。
Guarded Suspension 模式是 Single Threaded Execution 模式的進階版本,因為 Single Threaded Execution 模式是用來保護共享變數一次只能有一個執行緒存取共享變數,而 Guarded Suspension 模式有加
上條件判斷如果條件成立時才執行,沒有成有成立時就會一直進行等待的動作。
以下寫一個有關於 Guarded Suspension 模式,簡單的 Sample Code:
import java.util.LinkedList;
import java.util.Queue;
public class GuardedObject {
private final Queue<String> queue = new LinkedList<String>();
public synchronized String getQueue() {
while (queue.peek() == null) {
try {
wait();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
return queue.remove();
}
public synchronized void putQueue(String str) {
queue.offer(str);
notify();
}
}
GuardedObject 是一個 Guarded 物件,在 getQueue 裡面會先去判斷 queue 裡面有沒有東西如果沒有就會進行 wait 等待的動作,如果有就會把 queue 的值取出來。putQueue 就會把字串的值放入到 queue 裡面,然後通知不要等待了。
public class ExampleThread1 implements Runnable {
private GuardedObject guarded;
public ExampleThread1(GuardedObject guarded) {
this.guarded = guarded;
}
@Override
public void run() {
for (int i = 1 ; i <= 10 ; i++) {
String str = "message" + i;
this.guarded.putQueue(str);
try {
Thread.sleep(1000L);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
}
ExampleThread1 執行緒程式主要會將字串的值放入到 guarded 物件的 queue 裡面
public class ExampleThread2 implements Runnable {
private GuardedObject guarded;
public ExampleThread2(GuardedObject guarded) {
this.guarded = guarded;
}
@Override
public void run() {
while(true) {
String message = this.guarded.getQueue();
System.out.println(message);
}
}
}
ExampleThread2 執行緒程式的目的就是會將 Queue 裡面的資料取出來然後印到 console 上,主程式的呼叫如下程式:
public class Test {
public static void main(String args[]) {
GuardedObject guarded = new GuardedObject();
Thread thread1 = new Thread(new ExampleThread1(guarded));
Thread thread2 = new Thread(new ExampleThread2(guarded));
thread1.start();
thread2.start();
}
}
主程式就會開啟 ExampleThread1 和 ExampleThread2,把資料放入 Queue 裡面和從 Queue 裡面取資料的執行緒程式,執行結果如下:
message1
message2
message3
message4
message5
message6
message7
message8
message9
message10