并发系列之四Guarded Suspension

前言

Guarded Suspension是指当现在并不适合马上执行某个操作时,就要求想要执行该操作的线程等待

Guarded Suspension

首先模拟一个案例
首先是表示请求的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.zwl.utest3;
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+"]";
}
}

一次存放请求以待使用的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.zwl.utest3;
import java.util.LinkedList;
public class RequestQueue {
//构造链表,用来保存请求
private final LinkedList queue=new LinkedList<>();
//有请求将最早的请求取出,没有则等待
public synchronized Request getRequest(){
while(queue.size()<=0){
try{
wait();
}catch(Exception e){
}
}
return (Request) queue.removeFirst();
}
//增加一个请求
public synchronized void putRequest(Request request){
queue.addLast(request);
notifyAll();
}
}

送出请求的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.zwl.utest3;
import java.util.Random;
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(){
//不断调用putrequest(),并且打印相关信息
for(int i=0;i<10000;i++){
Request request=new Request("No ."+i);
System.out.println(Thread.currentThread().getName()+" Request:"+request);
requestQueue.putRequest(request);
try {
Thread.sleep(random.nextInt(1000));
} catch (Exception e) {
// TODO: handle exception
}
}
}
}

接收请求的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.zwl.utest3;
import java.util.Random;
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(){
//不断调用getrequest()
for(int i=0;i<10000;i++){
Request request=requestQueue.getRequest();
System.out.println(Thread.currentThread().getName()+" Handlet:"+request);
try {
Thread.sleep(random.nextInt(1000));
} catch (Exception e) {
// TODO: handle exception
}
}
}
}

最后是测试

1
2
3
RequestQueue requestQueue=new RequestQueue();
new ClientThread(requestQueue, "A", 1314520l).start();
new ServerThread(requestQueue, "B", 5201314l).start();

测试结果

A Request:[ RequestNo .0]
B Handlet:[ RequestNo .0]
A Request:[ RequestNo .1]
B Handlet:[ RequestNo .1]
A Request:[ RequestNo .2]
B Handlet:[ RequestNo .2]
……

从测试结果可以看出,当发送请求时,接受并处理
而其中的关键方法是getRequest()中,当满足while里条件时,则调用wait,处于等待,直到收到通知,才从休息区出来,而这种一定要满足的条件,就称为Guarded Suspension的警戒条件

所以可将该模式抽象为如下
GuardedObject(被防伪的对象)参与者:当线程执行guardMethod时,只要满足警戒条件,就马上执行,当不成立时,就开始等待,而条件的成立与否,是与参与者的状态变化有关
guardMethod:防伪的方法
stateChangingMethod:状态改变的方法

热评文章