Guared Suspension设计模式
针对Guared Suspension设计模式,我们先结合一下现实生活中的例子来认识一下它。当你正在家换衣服时,门铃突然响了,原来是邮递员来送快递了,这时,因为正在换衣服出不去,所以只能喊道,“请稍等一下”,让快递员在门口稍等一会儿,换好衣服后,才说着“让你久等了”并打开门... Guared Suspension模式,Guared是被守护,被保卫,被保护的意思,Suspension则是暂停的意思。如果执行现在的处理会造成问题,就让执行处理的线程进行等待----这就是Guared Suspension模式。Guared Suspension模式通过让线程等待来保证实例的安全性,这正如你让快递员在门口等待,以保护个人隐私一样。 我们来看一下示例程序,先介绍一相关用到的类:Request类表示一个请求的类,RequestQueue类表示依次存放请求的类,ClientThread表示发送请求的类,ServerThread表示接收请求的类。 Request类用于表示请求,虽说是请求,但由于只是用于表示ClientThread传递给ServerThread的实例,所以不提供什么特殊处理,只有一个Name属性 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=" + name + "]"; } } RequestQueue类用于依次存放请求,定义了getRequest和putRequest两个方法。 getRequest方法会取出最先存放在在RequestQueue中的一个请求,作为其返回值,如果一个请求都没有,那就一直等待,直到其他某个线程执行putRequest. putRequest方法用于添加一个请求,当线程想要向RequestQueue中添加实例时可以调用该方法。 总的来说,RequestQueue通过putRequest放入Request实例,并按放入顺序使用getRequest取出Request实例,这种结构其实就是队列。 import java.util.LinkedList; import java.util.Queue; import com.Guared.pojo.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) { e.printStackTrace(); } } return queue.remove(); } public synchronized void putRequest(Request request) { queue.offer(request); notifyAll(); } } ClientThread类表示发送请求的线程,ClientThread持有RequestQueue的实例(requestQueue ),并连续调用该实例putRequest,放入请求,请求的名称依次为“No.0”,“No.1”,“No.2”.....为了错开发送请求(执行putRequest)的时间点。这里使用随机数0-1000作为睡眠的时间。 import java.util.Random; import com.Guared.pojo.Request; import com.Guared.queue.RequestQueue; 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) { e.printStackTrace(); } } } } ServerThread类表示接收请求的线程,也持有RequestQueue的实例(requestQueue )。ServerThread使用getRequest方法来接收请求。与ClientThread一样,使用随机数0-1000作为睡眠的时间。 import java.util.Random; import com.Guared.pojo.Request; import com.Guared.queue.RequestQueue; 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) { e.printStackTrace(); } } } } Main类运行代码 import com.Guared.queue.RequestQueue; import com.Guared.thread.ClientThread; import com.Guared.thread.ServerThread; public class Main { public static void main(String[] args) { RequestQueue requestQueue = new RequestQueue(); new ClientThread(requestQueue, "jack", 3141592L).start(); new ServerThread(requestQueue, "tom", 6535877L).start(); } } 结果能看出,jack会一直发送请求,而tom则会不断地处理请求。 这就是我们介绍的Guared Suspension模式,在该模式中,线程是否等待取决于守护条件,其实Guared Suspension模式是在Single Threaded Execution模式的基础上附加了条件而形成的,也就是说Guared Suspension模式是类似于“附加条件的synchronized”这样的模式。
|