java多线程之Guarded Suspension模式

Guarded Suspension模式(等我准备好哦)

Single Threaded Execution模式中,只要有一个线程进入临界区,其他线程就无法进入,只能等待。而在Guarded Suspension模式中,线程是否等待取决于守护条件。Guarded Suspension模式是在Single Threaded Execution模式的基础上附加了条件而形成的。

如下一段代码实例:

 

request用于表示请求,表示ClientThread传递给ServerThread的实例

public class Request {

private final String name;

public Request(String name) {

super();

this.name = name;

}

public String getName() {

return name;

}

public String toString(){

return "[Request"+ name+"]";

}

}

RequestQueue类用于依次存放请求,类中定义了getRequest方法和putRequest方法

getRequest方法会取出最先存放在requestQueue中的一个请求,作为其返回值。如果一个请求都没有,那么就一直等待,直到其他线程执行putRequest

putRequest方法用于添加一个请求。当线程想要向RequestQueue中添加Request实例时,可以调用该实例方法。

public class RequestQueue {

private final Queue<Request> queue = new LinkedList<Request>();

public synchronized Request getRequest(){

while(queue.peek()==null){//守护条件

try {

wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

return queue.remove();

}

public synchronized void putRequest(Request request){

queue.offer(request);

notifyAll();

}

}

CientThread 类用于表示发送请求的线程。ClientThread持有RequestQueue的实例,并连续调用该实例的putRequest,放入请求,请求的名称依次为NO1,NO2.....

为了错开发送请求的时间点,使用random随机生成了01000之间的数,来作为sleep的时间(以毫秒为单位)

public class ClientThread extends Thread{

private final Random random;

private final RequestQueue requestQueue;

public ClientThread(RequestQueue requestQueue,String name,long seed){

this.requestQueue = requestQueue;

this.random = new Random(seed);

}

public void run(){

for (int i = 0; i < 1000; 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 (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

ServerThread类用于表示接收请求的线程。该类持有RequestQueue的实例 (requestQueue.

ServerThread使用getRequest方法接收请求

 

public class ServerThread  extends Thread{

private final Random random;

private final RequestQueue requestQueue;

public ServerThread(RequestQueue requestQueue,String name,long seed){

this.requestQueue = requestQueue;

this.random = new Random(seed);

}

public void run(){

for (int i = 0; i < 1000; i++) {

Request request = requestQueue.getRequest();

System.out.println(Thread.currentThread().getName()+"handles:"+request);

try {

Thread.sleep(random.nextInt(1000));

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

Main类会首先创建RequestQueue的实例(requestQueue,然后分别创建名为Alice的实例ClientThread和名为Boddy的实例ServerThread,并将requestQueue传给这两个实例,最后执行start.

public class Main {

public static void main(String[] args) {

RequestQueue requestQueue = new RequestQueue();

new ClientThread(requestQueue, "Alice", 3141592L).start();;

new ClientThread(requestQueue, "Bobby", 6535897L).start();;

}

}

GuardedObject 角色是一个持有被守护的方法的类.当线程执行guardedMethod方法时,如果条件成立,则可以立即执行,当守护条件不成立,则进行等待。

三大特征:

存在循环

存在条件检查

因为某种原因而等待

guarded supension :被守护而暂停执行的含义

guarded wait:被守护而等待

采用LinkedBlockingQueue时,实例程序中的RequestQueue可以被简化。

take方法用于取出队首的元素(将队头元素出队,如果队列空了,一直阻塞,直到队列不为空或者线程被中断),put方法用于向队列末尾添加元素(在队尾插入一个元素,如果队列满了,一直阻塞,直到队列不满了或者线程被中断)。这两个方法都进行了封装。因为这两个方法已经考虑了互斥的方法,所以无需声明为synchroized方法。

public class RequestQueue {

private final BlockingQueue<Request> queue = new LinkedBlockingQueue<Request>();

public Request getRequest(){

Request req = null;

try {

req = queue.take();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}//取出队首元素

return req;

}

public void putRequest(Request request){

try {

queue.put(request);//向队列末尾添加元素

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

LinkedListLinkedBlockingQueue的比较

 

对于Guarded Supension模式的总结:

该模式存在一个持有状态的对象,只有在这个对象的状态满足条件的情况下,才会允许现在执行目标处理。所以,我们先将这个对象的满足条件作为它的“守护条件”,然后,在执行这个目标处理之前,检查守护条件是否成立,只有当守护条件成立时,线程才会执行目标处理,而当守护条件不成立时,线程就会一直等到成立为止,使用while条件嵌套检查条件,wait()执行等待,使用notifyAll()方法进行通知。这就是Guarded Suspension模式。

猜你喜欢

转载自blog.csdn.net/qq_31350373/article/details/80312375
今日推荐