该模式中存在一个持有状态的对象。该对象只有在自身的状态合适时,才会允许线程执行目标处理。为此,我们需要首先将对象的合适状态表示为“守护条件”。然后,在执行目标处理之前,检查守护条件是否成立。只有当守护条件成立时,线程才会执行目标处理;而当守护条件不成立时,线程就会一直等到成立为止。
JAVA中是使用while 语句来检查条件,使用wait 方法来执行等待的。当条件发生变化时,使用notify / notifyall 方法发出通知。
示例程序:
名字 | 说明 |
Request | 表示一个请求的类 |
RequestQueue | 依次存放请求的类 |
ClientThread | 发送请求的类 |
ServerThread | 接收请求的类 |
Main | 测试程序行为的类 |
代码示例:
package guardedsuspension;
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();
}
}
package guardedsuspension;
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 + " ]";
}
}
package guardedsuspension;
import java.util.Queue;
import java.util.LinkedList;
public class RequestQueue {
private final Queue<Request> queue = new LinkedList<Request>();
public synchronized Request getRequest() {
while (queue.peek() == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
return queue.remove();
}
public synchronized void putRequest(Request request) {
queue.offer(request);
notifyAll();
}
}
package guardedsuspension;
import java.util.Random;
public class ClientThread extends Thread {
private final Random random;
private final 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) {
}
}
}
}
package guardedsuspension;
import java.util.Random;
public class ServerThread extends Thread {
private final Random random;
private final 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) {
}
}
}
}