导语
  什么是Guarded Suspension模式,Suspension 意思是挂起,暂停的。而Guarded则表示担保的意思,连起来的就是确保挂起。也就是说当线程访问某个对象的时候,发现条件不满足,就暂时挂起等待条件满足的时候再次发起访问,这一点与Balking设计模式正好是相反的(Balking在遇到条件不满足的时候回放弃)。在Java并发包中BlockingQueue大量的使用了Guarded Suspension设计模式

文章目录

  • Guarded Suspension设计模式
    • 什么是Guarded Suspension 设计模式
    • Guarded Suspension 示例
    • 总结

Guarded Suspension设计模式

什么是Guarded Suspension 设计模式

  Suspension 表示挂起、暂停的意思,而Guarded 则是担保的意思,连起来就是确保挂起。也就是当线程访问某个对象的时候,发现条件不满足,就暂时的挂起当条件满足的时候再次进行访问,这个设计与Balking设计模式刚好相反(Balking在遇到条件不满足的时候回主动放弃)
  Guarded Suspension 设计模式是很多的设计模式的基础,例如生产消费模式,Worker Thread设计模式,等等。在Java并发包中的BlockingQueue也使用到了Guarded Suspension 设计模式。

在Java源码中java.util.concurrent.ArrayBlockingQueue类为BlockingQueue接口的实现类其中有两个方法是值得关注的


public boolean offer(E e) {checkNotNull(e);final ReentrantLock lock = this.lock;lock.lock();try {if (count == items.length)return false;else {enqueue(e);return true;}} finally {lock.unlock();}
}private void enqueue(E x) {// assert lock.getHoldCount() == 1;// assert items[putIndex] == null;final Object[] items = this.items;items[putIndex] = x;if (++putIndex == items.length)putIndex = 0;count++;notEmpty.signal();
}public E take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (count == 0)notEmpty.await();return dequeue();} finally {lock.unlock();}
}private E dequeue() {// assert lock.getHoldCount() == 1;// assert items[takeIndex] != null;final Object[] items = this.items;@SuppressWarnings("unchecked")E x = (E) items[takeIndex];items[takeIndex] = null;if (++takeIndex == items.length)takeIndex = 0;count--;if (itrs != null)itrs.elementDequeued();notFull.signal();return x;
}

  根据上面的思路设计了如下的实例

Guarded Suspension 示例

public class GuardedSuspensionQueue {//定义存放Integer类型的Queueprivate final LinkedList<Integer> queue = new LinkedList<>();//定义queue的最大容量为100private final int LIMIT = 100;//向queue中插入数据,如果queue中的元素超过最大容量,则会陷入阻塞public void offer(Integer data) throws InterruptedException {synchronized (this){//判断queue的当前元素是否超过LIMITwhile (queue.size()>=LIMIT){//当前线程进入到阻塞this.wait();}//插入元素并呼气take线程queue.addLast(data);this.notifyAll();}}//从队列中获取元素,如果队列此时为空,自会使得当前线程阻塞public Integer take() throws InterruptedException {synchronized(this){//如果队列为空while (queue.isEmpty()){//则挂起当前线程this.wait();}//通知offer线程可以继续插入数据this.notifyAll();return queue.removeFirst();}}
}

  在GuardedSuspensionQueue中,需要保证线程安全的地方是queue,分别在take方法和offer方法中对应的临界值为空或者100的时候,当queue中的数据已经满了,如果线程调用了offer方法则会被挂起,同样的如果当这个queue没有数据的时候会调用take方法也会被挂起。这样就保证了线程的安全性。

  Guarded Suspension设计模式是一个比较基础的设计模式,它关注的是当某个条件不满足时候的操作,从而防止出现数据不一致或者是超过临界值的控制范围。如下图

  对于数据操作的空间就只有蓝色部分的内存,如果queue队列中的数据满的时候,对于所有的线程写入操作都进入到了挂起状态。当然当queue为空的时候对于所有线程的读取操作就进入到了挂起状态。通过这样可以保证了queue的高效利用率。不需要在频繁的创建和销毁队列。保证了公共资源的线程安全。至于具体有那些线程消费公共队列中的内容就是线程处理的问题。

总结

  相对来说Guarded Suspension设计模式并不是一个复杂的模式而是比较简单的一个模式,从上面例子中可以看出使用也相对比较简单。Guarded Suspension 的关注点还是在于临界值的是否满足条件。当达到设置的临界值是相关线程会被挂起。在很多的设计场景中都有这种设计模式的影子。

Java高并发编程详解系列-Guarded Suspension设计模式相关推荐

  1. Java高并发编程详解系列-线程上下文设计模式及ThreadLocal详解

    导语   在之前的分享中提到过一个概念就是线程之间的通信,都知道在线程之间的通信是一件很消耗资源的事情.但是又不得不去做的一件事情.为了保证多线程线程安全就必须进行线程之间的通信,保证每个线程获取到的 ...

  2. Java高并发编程详解系列-单线程执行设计模式

    引言 首先介绍的这个技术有一个比较高大尚的英文名字叫做Single Thread Execution也就是说在同一时刻只能有一个线程访问共享资源,也就是说共享资源同一时间只能被一个线程访问,而这个共享 ...

  3. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  4. Java高并发编程详解系列-7种单例模式

    引言 在之前的文章中从技术以及源代码的层面上分析了关于Java高并发的解决方式.这篇博客主要介绍关于单例设计模式.关于单例设计模式大家应该不会陌生,作为GoF23中设计模式中最为基础的设计模式,实现起 ...

  5. Java高并发编程详解系列-Future设计模式

    导语   假设,在一个使用场景中有一个任务需要执行比较长的时间,通常需要等待任务执行结束之后或者是中途出错之后才能返回结果.在这个期间调用者只能等待,对于这个结果Future设计模式提供了一种凭据式的 ...

  6. Java高并发编程详解系列-类加载

    之前在写关于JVM的时候提到过类加载机制,类加载机制也是在Java面试中被经常问道的一个问题,在这篇博客中就来了解一下关于类加载的知识. 类加载   在JVM执行Java程序的时候实际上执行的编译好的 ...

  7. Java高并发编程详解系列-线程安全数据同步

    在多线程中最为复杂和最为重要的就是线程安全.多个线程访问同一个对象的时候会导致线程安全问题.通过加锁可以避免这种问题.但是在串行执行的过程中又不用考虑线程安全问题,而使用串行程序效率低没有办法将CPU ...

  8. Java高并发编程详解系列-不可变对象设计模式

    导语   在开发中涉及到的所有关于多线程的问题都离不开共享资源的存在.那么什么是共享资源,共享资源就是被多个线程共同访问的数据资源,而且每个线程都会引起它的变化.伴随共享资源而生的新问题就是线程安全, ...

  9. Java高并发编程详解系列-线程上下文类加载

    前面的分享中提到的最多的概念就是关于类加载器的概念,但是当我们查看Thread源码的时候会发现如下的两个方法,这两个方法就是获取或者设置线程的上下文类加载器的方法,那么为什么要设置这两个方法呢?这个就 ...

最新文章

  1. 邮箱性质--全选单选的操作和传值 用属性的name传值
  2. Flying to the Mars
  3. 说一说ffmpeg到处都在使用的ff_thread_once函数
  4. T(n) = 25T(n/5)+n^2的时间复杂度 计算方法
  5. AQS源码阅读笔记(一)
  6. uva 1626——Brackets sequence
  7. spring基础——<bean>scope属性
  8. C语言之文件读写探究(四):fwrite、fread(一次读写一块数据(二进制操作))
  9. Linux下SVN创建新的项目
  10. static,inline,volatile的作用
  11. ListView分页加载数据
  12. “百度快照劫持”到底是什么意思?
  13. python对数正态分布函数_python中的对数正态分布
  14. 最新微信小程序获取音频时长与实时获取播放进度
  15. NOIP模拟赛 17.10.10
  16. android 4.5屏幕,屏幕大也不怕 4.5吋起大屏续航手机推荐
  17. 大众中国纯电动战略“水土不服”?理想ONE冲击月销过万目标
  18. Java处理生僻字的问题
  19. 随机信号处理笔记 - ING
  20. 使用树莓派构建嵌入式C++调试环境

热门文章

  1. lora信号测试小助手_433m无线收发模块LoRaF30如何进行距离测试
  2. python数据按照分组进行频率分布_python实现读取类别频数数据画水平条形图
  3. python 打开excel并在屏幕上呈现_excel-检查文件是否在Python中打开
  4. Linux容器能否弥补IoT的安全短板?
  5. 《转载》struts旅程《2》
  6. 对request,session,application作用域形象理解
  7. 九个PHP很有用的功能
  8. Firefly 3288又一次制作android和lubuntu双系统固件
  9. 《iOS 9 开发指南》——第6章,第6.7节iOS 9控件的属性
  10. 研磨数据结构与算法-13删除二叉树节点