【Java学习笔记】19:Guarded Suspension Pattern
2017-06-09 09:43
585 查看
Guarded Suspension Pattern表示当前并不适合马上执行某个操作时,就要求想要执行该操作的线程等待,以保证实例的安全性。Java中用while语句来测试条件,不满足时用wait方法来等待。而当条件更改后,用notify/notifyAll方法唤醒,直至再次获取锁定执行。
*请求的实例类Request.java
*请求队列RequestQueue.java
在RequestQueue类中的getRequest方法用了一个while语句,必须要满足queue.size()>0才执行后面的具体实现。像这样一定要满足的条件,称为Guarded Suspension Pattern的警戒条件。当线程抵达while语句的时候,会分为满足和不满足警戒条件两种情况,当警戒条件成立时,线程不会进入while块,而是执行后面的语句。当警戒条件不成立时,说明当前并不适合马上执行这个操作,就进入while块。在这里是线程执行this的wait方法,然后进入this的等待区,并解除this的锁定。正在wait的线程,期望警戒条件成立时,收到notify/notifyAll,然后退出等待区,不过还要等到再次获取锁定才能执行。
*送出请求的线程类ClientThread.java
*接受请求的线程类ServerThread.java
*测试类Main.java
部分运行结果:
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防卫的方法外,还应有更改实例状态(特别是用来改警戒条件)的方法。
*等待端的范例
*唤醒端的范例
*请求的实例类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();
相关文章推荐
- Java学习札记19:详解Java中的Pattern和Matcher
- 【Java学习笔记】基础知识学习19【一个大文件的复制方法】
- 19. JAVA 网络编程 Part 1 (IP与InetAddress类、URL与URLConnection类、URLEncoder与URLDecoder类、TCP&UDP)---- 学习笔记
- JAVA学习笔记19——String2_StringBuilder
- [置顶] JavaSE学习笔记_19:Java-GUI
- 设计模式学习笔记---迭代器模式iterator pattern(Java版)
- 区别 String 类 和 StringBuffer 类 -Java 学习笔记 (19)
- 设计模式学习笔记--命令模式command pattern(Java版)
- Java学习笔记19
- Java之学习笔记(19)-----------包装类和匿名类
- Java 学习笔记19:深入Serializable
- Java学习笔记_19_String类
- java学习笔记19——静态内部类
- 设计模式学习笔记--中介者模式Mediator pattern(Java版)
- Java线程之Guarded Suspension Pattern和Balking Pattern
- Java 学习个人笔记(二)(March 19,2013 )
- 黑马程序员_JAVA 学习笔记19 WEB篇6
- java个人学习笔记19(多生产者多消费者+循环判断标记+notifyAll()+Lock+Condition)
- java学习笔记-设计模式19(命令模式)
- 【8-19】java学习笔记01