• Java -- 每日一问:并发包中的 ConcurrentLinkedQueue 和 LinkedBlockingQueue 有什么区别?


    image.png

    典型回答

    有时候我们把并发包下面的所有容器都习惯叫作并发容器,但是严格来讲,类似 ConcurrentLinkedQueue 这种“Concurrent*”容器,才是真正代表并发。

    关于问题中它们的区别:

    • Concurrent 类型基于 lock-free,在常见的多线程访问场景,一般可以提供较高吞吐量。

    • LinkedBlockingQueue 内部则是基于锁,并提供了 BlockingQueue 的等待性方法。

    不知道你有没有注意到,java.util.concurrent 包提供的容器(Queue、List、Set)、Map,从命名上可以大概区分为 Concurrent*、CopyOnWrite和 Blocking等三类,同样是线程安全容器,可以简单认为:

    • Concurrent 类型没有类似 CopyOnWrite 之类容器相对较重的修改开销。

    • 但是,凡事都是有代价的,Concurrent 往往提供了较低的遍历一致性。你可以这样理解所谓的弱一致性,例如,当利用迭代器遍历时,如果容器发生修改,迭代器仍然可以继续进行遍历。

    • 与弱一致性对应的,就是我介绍过的同步容器常见的行为“fail-fast”,也就是检测到容器在遍历过程中发生了修改,则抛出 ConcurrentModificationException,不再继续遍历。

    • 弱一致性的另外一个体现是,size 等操作准确性是有限的,未必是 100% 准确。

    • 与此同时,读取的性能具有一定的不确定性。

    一课一练

    今天留给你的思考题是,指定某种结构,比如栈,用它实现一个 BlockingQueue,实现思路是怎样的呢?

    栈来实现blockqueue,个人感觉比较好的有
    方案一:总共3个栈,其中2个写入栈(A、B),1个消费栈栈C(消费数据),但是有1个写入栈是空闲的栈(B),随时等待写入,当消费栈©中数据为空的时候,消费线程(await),触发数据转移,原写入栈(A)停止写入,,由空闲栈(B)接受写入的工作,原写入栈(A)中的数据转移到消费栈(C)中,转移完成后继续(sign)继续消费,2个写入栈,1个消费栈优点是:不会堵塞写入,但是消费会有暂停

    方案二:总共4个栈,其中2个写入栈(A、B),2个消费栈(C、D),其中B为空闲的写入栈,D为空闲的消费栈,当消费栈(C)中的数据下降到一定的数量,则触发数据转移,这时候A栈停止写入,由B栈接受写入数据,然后将A栈中的数据转入空闲的消费栈D,当C中的数据消费完了后,则C栈转为空闲,D栈转为激活消费状态,当D栈中的数据消费到一定比例后,重复上面过程,该方案优点即不堵塞写入,也不会造成消费线程暂停

    你的朋友是不是也在准备面试呢?你可以“请朋友读”,把今天的题目分享给好友,或许你能帮到他。

  • 相关阅读:
    Vue.js+SpringBoot开发大病保险管理系统
    NaN 的 注意点
    CRM软件系统趣味性——游戏化销售管理
    uniapp图片上传制作
    CSDN竞赛第四期季军 解题思路及参赛经历分享
    研发管理工具选型要考虑哪些内容?
    .NET关于 跳过SSL中遇到的问题
    计算sum=1+2...+n,要求number和sum的类型都是int,且sum在32位以内~
    【0230】PG内核底层事务(transaction)实现原理之基础篇
    Java 多线程的相关内容
  • 原文地址:https://blog.csdn.net/duoduo_11011/article/details/127703650