A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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类用于依次存放请求,定义了getRequestputRequest两个方法。
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”这样的模式。


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马