什么是Guarded Suspension设计模式
Suspension是“挂起”、“暂停”的意思,而Guarded则是“担保”的意思,连在一起就是确保挂起。当线程在访问某个对象时, 发现条件不满足,就暂时挂起等待条件满足时再次访问,这一点和Balking设计模式刚好相反(Balking在遇到条件不满足时会放弃)。 Guarded Suspension设计模式是很多设计模式的基础,比如生产者消费者模式,Worker Thread设计模式,等等,同样在Java 并发包中的BlockingQueue中也大量使用到了Guarded Suspension设计模式
Guarded Suspension的示例
package MutilThreadModel.GuardedSuspensionModel; import java.util.LinkedList; import java.util.concurrent.TimeUnit; /** * Created by JYM on 2019/1/10 * Guarded Suspension设计模式 * */ public class GuardedSuspensionQueue { //定义存放Integer类型的queue private final LinkedList<Integer> queue = new LinkedList<>(); //定义queue的最大容量为100 private final int LIMIT = 100; //往queue中插入数据,如果queue中的元素超过了最大容量,则会陷入阻塞 public void offer(Integer data) throws InterruptedException { synchronized (this) { //判断queue的当前元素是否超过了LIMIT while (queue.size() >= LIMIT) { //挂起当前线程,使其陷入阻塞 System.out.println("queue中的元素个数超过了LIMIT,当前线程被挂起,使其陷入阻塞状态!"); this.wait(); } //插入元素并且唤醒take线程 queue.addLast(data); this.notifyAll(); } } //从队列中获取元素,如果队列此时为空,则会使当前线程阻塞 public Integer take() throws InterruptedException { synchronized (this) { //判断如果队列为空 while (queue.isEmpty()) { //则挂起当前线程 System.out.println("queue中的元素个数为0,当前线程被挂起!"); this.wait(); } //通知offer线程可以继续插入数据了 this.notifyAll(); return queue.removeFirst(); } } //简单测试 public static void main(String[] args) { GuardedSuspensionQueue guardedSuspensionQueue = new GuardedSuspensionQueue(); //创建10个生产线程 for (int i=0;i<10;i++) { new Thread(()-> { try{ for (int j=1;j<15;j++) { guardedSuspensionQueue.offer(j); } }catch (InterruptedException e) { e.printStackTrace(); } slowly(); },"第"+(i+1)+"个生产线程").start(); } //创建2个消费线程 for (int i=0;i<10;i++) { new Thread(()-> { int result; try{ while (guardedSuspensionQueue.take() != null) { result=guardedSuspensionQueue.take(); System.out.println("取出队列中的第一个数据:"+result); } }catch (InterruptedException e) { e.printStackTrace(); } slowly(); },"第"+(i+1)+"个消费线程").start(); } } //暂时休眠 private static void slowly() { try{ TimeUnit.MILLISECONDS.sleep(1); }catch (Exception e) { e.printStackTrace(); } } } /** * 在GuardedSuspensionQueue中,我们需要保证线程安全的是queue,分别在take和offer方法中对应的临界值是queue为空和queue的数量>=100,当Queue中的 * 数据已经满时,如果有线程调用offer方法则会挂起(Suspension),同样,当queue没有数据的时候,调用take方法也会被挂起。 * Guarded Suspension模式是一个非常基础的设计模式,它主要关注的是当某个条件(临界值)不满足时将操作的线程正确地挂起, * 以防止出现数据不一致或者操作超过临界值的控制范围。 * */
总结:
Guarded Suspension设计模式并不复杂,但是它是很多其他线程设计模式的基础,比如生产者消费者模式,后文中的Thread Worker设计模式、Balking设计模式等,都可以看到Guarded Suspension模式的影子,Guarded Suspension的关注点在于临界值的条件是否满足,当达到设置的临界值时相关线程则会被挂起。