黑马程序员技术交流社区
标题: 【广州校区】【原创】认识Guared Suspension模式的设计 [打印本页]
作者: 瞧瞧嗨一波... 时间: 2018-11-1 15:41
标题: 【广州校区】【原创】认识Guared Suspension模式的设计
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”这样的模式。
| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |