【Java学习笔记】19:Guarded Suspension Pattern

Guarded Suspension Pattern表示当前并不适合马上执行某个操作时,就要求想要执行该操作的线程等待,以保证实例的安全性。Java中用while语句来测试条件,不满足时用wait方法来等待。而当条件更改后,用notify/notifyAll方法唤醒,直至再次获取锁定执行。


*请求的实例类Request.java

package day19;
//该类作为ClientThread传递给ServerThread的实例
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+"]";
	}
}

*请求队列RequestQueue.java

package day19;
import java.util.LinkedList;
//该类是用来依次存放请求的类
public class RequestQueue {
	private final LinkedList<Request> queue=new LinkedList<Request>();
	
	//在RequestQueue里所存放的请求中将最早传入的一个取出
	public synchronized Request getRequest()
	{
		while(queue.size()<=0)//请求队列里没有东西时等
		{
			try
			{
				wait();//该线程不再活动,置于等待状态,切换到其他线程运行
			}
			catch(InterruptedException e)
			{
				
			}
		}
		return (Request)queue.removeFirst();//返回队头
	}
	
	//增加一个请求到RequestQueue的队尾
	public synchronized void putRequest(Request request)
	{
		queue.addLast(request);//加入队尾,这时getRequest条件有机会满足了
		notifyAll();//那么就唤醒所有在等待的线程
	}
}

RequestQueue类中的getRequest方法用了一个while语句,必须要满足queue.size()>0才执行后面的具体实现。像这样一定要满足的条件,称为Guarded Suspension Pattern的警戒条件。当线程抵达while语句的时候,会分为满足和不满足警戒条件两种情况,当警戒条件成立时,线程不会进入while块,而是执行后面的语句。当警戒条件不成立时,说明当前并不适合马上执行这个操作,就进入while块。在这里是线程执行this的wait方法,然后进入this的等待区,并解除this的锁定。正在wait的线程,期望警戒条件成立时,收到notify/notifyAll,然后退出等待区,不过还要等到再次获取锁定才能执行。


*送出请求的线程类ClientThread.java

package day19;
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);//调用基类构造传入name
		this.requestQueue=requestQueue;
		this.random=new Random(seed);
	}
	public void run()
	{
		for(int i=0;i<100;i++)
		{
			Request request=new Request("No."+i);//生成一个请求
			System.out.println(Thread.currentThread().getName()+" requets "+request);
			requestQueue.putRequest(request);//增加这个请求到队尾
			try//延时
			{
				Thread.sleep(random.nextInt(1000));
			}
			catch(InterruptedException e)
			{
				
			}
		}
	}
}

*接受请求的线程类ServerThread.java

package day19;
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);//调用基类构造传入name
		this.requestQueue=requestQueue;
		this.random=new Random(seed);
	}
	public void run()
	{
		for(int i=0;i<100;i++)
		{
			Request request=requestQueue.getRequest();//从请求队列中获取一个请求
			System.out.println(Thread.currentThread().getName()+" handles "+request);
			try//延时
			{
				Thread.sleep(random.nextInt(1000));
			}
			catch(InterruptedException e)
			{
				
			}
		}
	}
}

*测试类Main.java

package day19;
public class Main {
	public static void main(String[] args) {
		RequestQueue requestQueue=new RequestQueue();//建立一个请求队列实例
		new ClientThread(requestQueue,"Alice",1234567L).start();//Alice送出请求
		new ServerThread(requestQueue,"Bobby",7654321L).start();//Bobby处理请求
	}
}

部分运行结果:

Alice requets [RequestNo.5]
Bobby handles [RequestNo.5]
Alice requets [RequestNo.6]
Alice requets [RequestNo.7]
Bobby handles [RequestNo.6]
Alice requets [RequestNo.8]
Alice requets [RequestNo.9]
Bobby handles [RequestNo.7]
Bobby handles [RequestNo.8]
Bobby handles [RequestNo.9]

Guarded Suspension Pattern中,除了有被while-wait防卫的方法外,还应有更改实例状态(特别是用来改警戒条件)的方法。


*等待端的范例

while(!ready)
{
wait();
}
//后面做该做的事

*唤醒端的范例

ready=true;//改变实例状态而使警戒条件成立时
notifyAll();



你可能感兴趣的:(线程,synchronized,wait,notify,notifyAll)