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

 2023-09-15 阅读 20 评论 0

摘要:导语   什么是Guarded Suspension模式,Suspension 意思是挂起,暂停的。而Guarded则表示担保的意思,连起来的就是确保挂起。也就是说当线程访问某个对象的时候,发现条件不满足,就暂时挂起等待条件满足的时候再次发起访问,这一点与

导语
  什么是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源码中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 的关注点还是在于临界值的是否满足条件。当达到设置的临界值是相关线程会被挂起。在很多的设计场景中都有这种设计模式的影子。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/60439.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息