定义:
Suspension模式通过线程等待来保证实例的安全性。
引例
名字 | 说明 |
Request | 请求类 |
RequestQueue | 依次存放求情的类 |
ClientThread | 发送请求类 |
ServerThread | 接受请求类 |
Main | 测试行为类 |
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 RequestQueue {
// 有点像消息队列。生产者与消费者
private final LinkedList queue = new LinkedList();
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();
}
}
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) {
}
}
}
}
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 Main {
public static void main(String[] args) {
RequestQueue requestQueue = new RequestQueue();
new ClientThread(requestQueue, "Alice", 3141592L).start();
new ServerThread(requestQueue, "Bobby", 6535897L).start();
}
}
结果:
Alice requests [ Request No.0 ]
Bobby handles [ Request No.0 ]
Alice requests [ Request No.1 ]
Alice requests [ Request No.2 ]
Bobby handles [ Request No.1 ]
Bobby handles [ Request No.2 ]
Alice requests [ Request No.3 ]
Bobby handles [ Request No.3 ]
Alice requests [ Request No.4 ]
Bobby handles [ Request No.4 ]
Alice requests [ Request No.5 ]
Alice requests [ Request No.6 ]
Suspension模式 中的角色
GuardedObject(被守护的对象)是一个持有被守护方法的类。当线程执行守护方法时,若守护条件成立则执行,若不成立则等待。守护条件的成立会随着被守护的对象状态发生改变。
问题思考:
死锁的问题,A与B通过发送请求对话。
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 RequestQueue {
private final LinkedList queue = new LinkedList();
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();
}
}
public class TalkThread extends Thread {
private RequestQueue input;
private RequestQueue output;
public TalkThread(RequestQueue input, RequestQueue output, String name) {
super(name);
this.input = input;
this.output = output;
}
public void run() {
System.out.println(Thread.currentThread().getName() + ":BEGIN");
for (int i = 0; i < 20; i++) {
// 取得对方的请求
Request request1 = input.getRequest();
System.out.println(Thread.currentThread().getName() + " gets " + request1);
//加上一个感叹号(!)传给对方
Request request2 = new Request(request1.getName() + "!");
System.out.println(Thread.currentThread().getName() + " puts " + request2);
output.putRequest(request2);
}
System.out.println(Thread.currentThread().getName() + ":END");
}
}
public class Main {
public static void main(String[] args) {
RequestQueue requestQueue1 = new RequestQueue();
RequestQueue requestQueue2 = new RequestQueue();
// 种下一个种子,防止发生死锁
// requestQueue1.putRequest(new Request("Hello"));
new TalkThread(requestQueue1, requestQueue2, "Alice").start();
new TalkThread(requestQueue2, requestQueue1, "Bobby").start();
}
}
结果
Bobby:BEGIN
Alice:BEGIN
如何解决呢? 放开注释,事先种下一个请求。这样就不会出现相互等待对方发起第一次会话。
我们继续向下看!这样写有什么意思呢??
public class Channel {
private RequestQueue input;
private RequestQueue output;
public Channel(RequestQueue input, RequestQueue output) {
this.input = input;
this.output = output;
}
public RequestQueue getInput() {
return input;
}
public RequestQueue getOutput() {
return output;
}
}
public class TalkThread extends Thread {
private Channel channel;
public TalkThread(Channel channel, String name) {
super(name);
synchronized (channel) {
this.channel = channel;
}
}
public void run() {
System.out.println(Thread.currentThread().getName() + ":BEGIN");
for (int i = 0; i < 20; i++) {
// 取得对方的请求
Request request1 = channel.getInput().getRequest();
System.out.println(Thread.currentThread().getName() + " gets " + request1);
// 加上一个感叹号(!)传给对方
Request request2 = new Request(request1.getName() + "!");
System.out.println(Thread.currentThread().getName() + " puts " + request2);
channel.getOutput().putRequest(request2);
}
System.out.println(Thread.currentThread().getName() + ":END");
}
}
public class Main {
public static void main(String[] args) {
RequestQueue requestQueue1 = new RequestQueue();
RequestQueue requestQueue2 = new RequestQueue();
Channel channel = new Channel(requestQueue1, requestQueue1);
// 种下一个种子,防止发生死锁
requestQueue1.putRequest(new Request("Hello"));
new TalkThread(channel, "Alice").start();
new TalkThread(channel, "Bobby").start();
}
}
有点像netty通信管道的意思!!自己体会一下