JUC并发工具---阻塞队列

打印 上一主题 下一主题

主题 1004|帖子 1004|积分 3022

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
阻塞队列也就是BlockingQueue,它是一个接口,继承了Queue接口,是队列的一种。
使用阻塞队列的话,就不会发生线程安全问题,降低我们的开发的难度和工作量(不用我们自己思量线程安全,而是转移到队列上),实现了隔离,提升了安全性。
主要并发队列关系图

[外链图片转存中…(img-7Uko6uLa-1734860138402)]
阻塞队列非阻塞队列DequeArrayBlockingQueueConcurrentLinkedQueue 用CAS保证了线程安全双端队列LinkedBlockingQueueSynchronousQueueDelayQueuePriorityBlockingQueueLinkedTransferQueue 阻塞队列常用方法

add,remove,element

抛出非常
add():往队列里添加一个元素,如果队列满了,就会抛出非常来提示队列已满
remove():删除元素,如果我们删除的队列是空的,remove方法就会抛出非常
element():返回队列的头部节点但不删除,如果我们用这个方法去操纵一个空队列,想获取队列的头结点,可是由于队列是空的,会抛出和前面remove方法一样的非常
offer,poll,peek

返回操纵效果但不抛出非常
对应add(),remove(), element()方法
put,take

阻塞
put方法插入元素时:如果队列没有满,就和普通的插入一样是正常的插入,如果队列已满就无法继续插入,则阻塞,直到队列里有了空闲空间。如果后续队列有了空闲空间,队列就会解除阻塞状态,并把需要添加的数据添加到队列中
take 方法的功能:获取并移除队列的头结点,通常在队列里有数据的时候是可以正常移除的,可是一旦实行take方法的时候,队列里无数据,则阻塞,一旦队列里有数据就会立即解除阻塞状态,并且取到数据
常见的阻塞队列

ArrayBlockingQueueLinkedBlockingQueeuSynchronousQueuePriorityBlockingQueueDelayQueue有界,创建容量后不可扩容无界,默认容量是整数的最大值Integer.MAX_VALUE容量为0,所做的就是直接转达支持优先级的无界阻塞队列,后续可以扩容无界内部使用数组存储元素内部使用链表实现可以通过初始化构造器参数Comparator来指定排序规则。插入的对象必须是可以Comparable的可以设定让队列中的使命延迟多久之后实行。
里面的元素必须实现Delayed接口利用ReentrantLock实现线程安全次取数据都要先阻塞,直到有数据被放入,同理,每次放数据的时候也会阻塞,直到有消费者来取 阻塞和非阻塞队列的并发安全原理

[外链图片转存中…(img-Bu1eKWAi-1734860138402)]
[外链图片转存中…(img-kGcXpc58-1734860138402)]
如何选择

功能好比是否需要阻塞队列帮我们排序,如优先级排序、延迟实行等
如果有这个需要,我们就必须选择类似于PriorityBlockingQueue之类的有排序能力的阻塞队列容量或者说是否有存储的要求,照旧只需要“直接转达”
在思量这一点的时候,我们知道前面介绍的那几种阻塞队列,有的是容量固定的
如ArrayBlockingQueue;有的默认是容量无限的,如LinkedBlockingQueue;而有的里面没有任何容
量,如 SynchronousQueue;而对于DelayQueue 而言,它的容量固定就是Integer.MAX_VALUE
所以差别阻塞队列的容量是千差万别的,我们需要根据使命数量来推算出合适的容量,从而去选取合适
的 BlockingQueue可否扩容因为有时我们并不能在初始的时候很好的准确估计队列的大小,因为业务可能有高峰期、低谷期如果一开
始就固定一个容量,可能无法应对所有的情况,也是不合适的,有可能需要动态扩容
如果我们需要动态扩容的话,那么就不能选择ArrayBlockingQueue,因为它的容量在创建时就确定了,
无法扩容
相反,PriorityBlockingQueue即使在指定了初始容量之后,后续如果有需要,也可以自动扩容所以我们
可以根据是否需要扩容来选取合适的队列内存布局在上一课时我们分析过ArrayBlockingQueue的源码,看到了它的内部布局是“数组”的情势
和它差别的是,LinkedBlockingQueue的内部是用链表实现的
所以这里就需要我们思量到,ArrayBlockingQueue没有链表所需要的“节点”,空间利用率更高
所以如果我们对性能有要求可以从内存的布局角度去思量这个问题性能好比LinkedBlockingQueue由于拥有两把锁,它的操纵粒度更细,在并发程度高的时候,相对于只有
一把锁的ArrayBlockingQueue性能会更好
另外,SynchronousQueue性能每每优于其他实现,因为它只需要“直接转达”,而不需要存储的过
程。如果我们的场景需要直接转达的话,可以优先思量SynchronousQueue
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表