Java核心技术面试精讲
杨晓峰
前Oracle首席工程师
立即订阅
43144 人已学习
课程目录
已完结 43 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 以面试题为切入点,有效提升你的Java内功
免费
模块一 Java基础 (14讲)
第1讲 | 谈谈你对Java平台的理解?
第2讲 | Exception和Error有什么区别?
第3讲 | 谈谈final、finally、 finalize有什么不同?
第4讲 | 强引用、软引用、弱引用、幻象引用有什么区别?
第5讲 | String、StringBuffer、StringBuilder有什么区别?
第6讲 | 动态代理是基于什么原理?
第7讲 | int和Integer有什么区别?
第8讲 | 对比Vector、ArrayList、LinkedList有何区别?
第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同?
第10讲 | 如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全?
第11讲 | Java提供了哪些IO方式? NIO如何实现多路复用?
第12讲 | Java有几种文件拷贝方式?哪一种最高效?
第13讲 | 谈谈接口和抽象类有什么区别?
第14讲 | 谈谈你知道的设计模式?
模块二 Java进阶 (16讲)
第15讲 | synchronized和ReentrantLock有什么区别呢?
第16讲 | synchronized底层如何实现?什么是锁的升级、降级?
第17讲 | 一个线程两次调用start()方法会出现什么情况?
第18讲 | 什么情况下Java程序会产生死锁?如何定位、修复?
第19讲 | Java并发包提供了哪些并发工具类?
第20讲 | 并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?
第21讲 | Java并发类库提供的线程池有哪几种? 分别有什么特点?
第22讲 | AtomicInteger底层实现原理是什么?如何在自己的产品代码中应用CAS操作?
第23讲 | 请介绍类加载过程,什么是双亲委派模型?
第24讲 | 有哪些方法可以在运行时动态生成一个Java类?
第25讲 | 谈谈JVM内存区域的划分,哪些区域可能发生OutOfMemoryError?
第26讲 | 如何监控和诊断JVM堆内和堆外内存使用?
第27讲 | Java常见的垃圾收集器有哪些?
第28讲 | 谈谈你的GC调优思路?
第29讲 | Java内存模型中的happen-before是什么?
第30讲 | Java程序运行在Docker等容器环境有哪些新问题?
模块三 Java安全基础 (2讲)
第31讲 | 你了解Java应用开发中的注入攻击吗?
第32讲 | 如何写出安全的Java代码?
模块四 Java性能基础 (3讲)
第33讲 | 后台服务出现明显“变慢”,谈谈你的诊断思路?
第34讲 | 有人说“Lambda能让Java程序慢30倍”,你怎么看?
第35讲 | JVM优化Java代码时都做了什么?
模块5 Java应用开发扩展 (4讲)
第36讲 | 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
第37讲 | 谈谈Spring Bean的生命周期和作用域?
第38讲 | 对比Java标准NIO类库,你知道Netty是如何实现更高性能的吗?
第39讲 | 谈谈常用的分布式ID的设计方案?Snowflake是否受冬令时切换影响?
周末福利 (2讲)
周末福利 | 谈谈我对Java学习和面试的看法
周末福利 | 一份Java工程师必读书单
结束语 (1讲)
结束语 | 技术没有终点
Java核心技术面试精讲
登录|注册

第20讲 | 并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?

杨晓峰 2018-06-21
在上一讲中,我分析了 Java 并发包中的部分内容,今天我来介绍一下线程安全队列。Java 标准库提供了非常多的线程安全队列,很容易混淆。
今天我要问你的问题是,并发包中的 ConcurrentLinkedQueue 和 LinkedBlockingQueue 有什么区别?

典型回答

有时候我们把并发包下面的所有容器都习惯叫作并发容器,但是严格来讲,类似 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% 准确。
与此同时,读取的性能具有一定的不确定性。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Java核心技术面试精讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(28)

  • sunlight001
    这个看着很吃力啊,都没接触过😂
    2018-06-21
    53
  • 丘壑
    栈来实现blockqueue,个人感觉比较好的有
    方案一:总共3个栈,其中2个写入栈(A、B),1个消费栈栈C(消费数据),但是有1个写入栈是空闲的栈(B),随时等待写入,当消费栈(C)中数据为空的时候,消费线程(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栈中的数据消费到一定比例后,重复上面过程,该方案优点即不堵塞写入,也不会造成消费线程暂停


    2018-09-13
    2
    14
  • 石头狮子
    实现课后题过程中把握以下几个维度,
    1,数据操作的锁粒度。
    2,计数,遍历方式。
    3,数据结构空,满时线程的等待方式,有锁或无锁方式。
    4,使用离散还是连续的存储结构。
    2018-06-21
    7
  • crazyone
    从上面这些角度,能够理解 ConcurrentLinkedDeque 和 LinkedBlockingQueue 的主要功能区别。 这段应该是 "ConcurrentLinkedDeque 和 LinkedBlockingDeque 的主要功能区别"
    2018-06-22
    5
  • 吕倩
    老师你好,在读ArrayBlockingQueue源码的时候,发现很多地方都有 final ReentrantLock lock = this.lock; 这样的语句,处于什么原因会将类变量复制一份到局部变量,然后再使用呢?
    2018-12-03
    4
  • 猕猴桃 盛哥
    {
        "test":[
            [
                89,
                90,
                [
                    [
                        1093,
                        709
                    ],
                    [
                        1056,
                        709
                    ]
                ]
            ]
        ]
    }

    测试题:这个json用java对象怎么表示?
    2018-06-22
    4
  • 无呢可称
    @Jerry银银。用两个栈可以实现fifo的队列

    2018-06-27
    3
  • 石头狮子
    实现课后题过程中把握以下几个维度,
    1,数据操作的锁粒度。
    2,计数,遍历方式。
    3,数据结构空,满时线程的等待方式,有锁或无锁方式。
    4,使用离散还是连续的存储结构。
    2018-06-21
    3
  • 拯救地球好累
    从几个问题来学习新的框架或工具:
    1.用来解决什么问题?常见的应用场景有哪些?
    2.jdk内部或第三方框架在什么场景中如何运用?
    3.有哪几种类似的实现或工具?它们之间有何区别?在结构层次上有何联系?
    4.从源码上看关键代码有哪几个地方?
    2019-05-20
    1
  • Lighters
    希望能够增加一些具体的业务使用场景,否则只是单纯的分析,太抽象了
    2019-04-27
    1
  • 南北少卿
    杨老师,你好,最近我debug过ConcurrentLinkedQueue的源码,第一次添加元素的时候,为什么head指向添加的元素,而tail指向自己,始终搞不明白,经过p.casNext(null, newNode)操作之后,这中间的变化到底是怎么回事?您能解答下吗?望指点.我的微信号:LEE794112629
    2018-12-14
    1
  • 酱了个油
    队列的一个问题是不能持久化、不能做到分布式,有时候考虑到系统可靠性,使用的机会不多。杨老师可以给一些使用队列的例子吗?
    2018-08-05
    1
  • 汉彬
    用栈实现BlockingQueue,我的理解是:栈是LIFO,BlockingQueue是FIFO,因此需要两个栈。take时先把栈A全部入栈到栈B,然后栈B出栈得到目标元素;put时把栈B全部入栈到栈A,然后栈A再入栈目标元素。相当于倒序一下。

    不知道理解对不对,请老师指出。
    2018-07-17
    1
  • 爱新觉罗老流氓
    杨老师,“与弱一致性对应的,就是我介绍过的同步容器常见的行为“fast-fail”,也就是检测到容器在遍历过程中发生了修改,则抛出 ConcurrentModificationException,不再继续遍历。”
    这一段落里,快速失败的英文在doc上是“fail-fast”,在ArrayList源码中文档可以搜到。
    还有,同步容器不应该是“fail-safe”吗?

    作者回复: 谢谢指出,我查查是不是我记反了

    2018-07-03
    1
  • Jerry银银
    用栈来实现BlockingQueue,换句话是说,用先进后出的数据结构来实现先进先出的数据结构,怎么感觉听起来不那么对劲呢?请指点
    2018-06-22
    1
  • 灰飞灰猪不会灰飞.烟灭
    老师 线程池中如果线程已经运行结束则删除该线程。如何判断线程已经运行结束了呢?源码中我看见按照线程的状态,我不清楚这些状态值哪来的。java代码有判断线程状态的方法吗?谢谢老师

    作者回复: 所谓结束是指terminated?正常的线程池移除工作线程,要么线程意外退出,比如任务抛异常,要么线程闲置,又规定了闲置时间;线程池中线程是把额外封装的,本来下章写了,内容篇幅超标移到后面了,慢慢来;有,建议学会看文档,自己找答案

    2018-06-21
    1
  • Paul Shan
    并发中的一致性是有代价的,如何支付这个代价延伸出不同的实现。ConcurrentLinkedQueue 就是提供较高的吞吐率而牺牲一部分一致性的解决方案,也就是遍历的时候,数据被修改了而不查,size也没有100%正确。要获得这些保证,就要加锁牺牲吞吐量 LinkedBlockingQueue 就是这种高准确度而相对较低吞吐量的解决方案。加入其他维度例如是否无限,Java还有其他选择。
    2019-11-25
  • 张三
    文章中关于生产者消费者的示例代码运行不能体现出blocking queue的特性,因为输出语句和操作不是原子性的,所以输出顺序会有问题
    2019-09-24
  • wengyifa
    if (c == capacity)
                signalNotFull();
    有点看不懂 take 方法中最后一段的内容,为何是在实际大小等于容量时,才去唤醒添加线程,而不是实际大小小于容量就去唤醒添加线程。在源码中 put 方法也看到类似的片段。
    if (c == 0)
                signalNotEmpty();
    老师能否解下惑?
    2019-08-05
    2
  • colin
    SynchronousQueue是不是相当于建立了一个“虫洞”?
    2019-06-14
收起评论
28
返回
顶部