JUC之Collections面经整理

先看Collections结构

Collections目录结构

面试常问问题:

1、ArrayBlockQueue和LinkedBlockingQueue有什么区别

答:二者都是通过reentrantLock进行加锁的,但是区别在于ArrayBlockQueue是读写不分离的,也就是说要么进行读操作,要么进行写操作,而且因为用的是ReentrantLock,所以一个线程是可以重复写或者读的;LinkedBlockingQueue则是读写分离,可以同时读或者写,但是因为用的是ReentrantLock,所以每次只能有一个线程读和一个写。这个需要专门注意下读和写的并发操作。

2、PriorityBlockingQueue是无界队列,基于数组,数据结构为二叉堆,数组的第一个节点也是树的根节点总是最小值



一、BlockingQueue

参见解读java并发队列BlockingQueue

1、BlockingQueue是双缓冲队列。BlockingQueue内部使用两条队列,允许两个线程同时向队列一个存储,一个取出操作。在保证并发安全的同时,提高了队列的存取效率。

2、常用的几种BlockingQueue:

(1)ArrayBlockingQueue(int i):规定大小的BlockingQueue,其构造必须指定大小。其所含的对象是FIFO顺序排序的。

(2)LinkedBlockingQueue()或者(int i):大小不固定的BlockingQueue,若其构造时指定大小,生成的BlockingQueue有大小限制,不指定大小,其大小由Integer.MAX_VALUE来决定。其所含的对象是FIFO顺序排序的。

(3)PriorityBlockingQueue()或者(int i):类似于LinkedBlockingQueue,但是其所含对象的排序不是FIFO,而是依据对象的自然顺序或者构造函数的Comparator决定。

(4)SynchronizedQueue():特殊的BlockingQueue,对其的操作必须是放和取交替完成。

3、常用方法

常用方法

4、应用

(1)生产者消费者模式:有了阻塞队列,我们实现生产者消费者模式只需要调用接口就行了,不用自己实现线程的阻塞和唤醒,也就是说阻塞队列接口的实现方式就是生产者消费者模式的实现。

(2)线程池:线程池的底层也用到了阻塞队列,其实它的本质也是生产者消费者模式,只不过这里的资源是线程。

(3)消息中间件:RabbitMQ等消息队列的底层数据结构就是用到了阻塞队列,因为它的模型也是生产者消费者模式。


二、CopyOnWriteArrayList(线程安全,解决iterator遍历的java.util.ConcurrentModificationException)

1、原理:写操作并不是直接修改原本的array,而是复制一份进行修改,同时也加了锁,在多线程的情况下不会复制出多个副本,其读操作没有任何锁,直接返回原本的array。

2、CopyOnWriteArrayList,对它的操作可以做到写写互斥、其他三个操作不互斥。

3、复制的原因是为了读写分离,为了在写的时候操作不阻塞也能不出现问题

未读写分离时,如果不阻塞读操作,由于读和写操作都不是原子操作,它们可能会交替执行,如:

例1

当一个线程执行到len = len + 1 的时候,另外一个线程来进行读操作了,比如执行getLast()方法,即执行get(len - 1),但是现在这个位置是没有赋值上的,这就出现了问题。但是如果修改时是赋值一份来修改,另外一个线程读的时候就没有任何影响。这也就是为什么在没有这个容器之前,只能坐到读读不加锁,读写、写读、写写都要加锁。有了这个容器,就可以只在写写的时候加锁了。

4、写操作的源码(通过ReentrantLock加锁实现)

写操作的源码

三、ConcurrentMap

1、ConcurrentHashMap

a、JDK1.7之前ConcurrentHashMap采用锁分段机制

ConcurrentHashMapJDK1.7

如图所示,ConcurrentHashMap默认分成了16个segment,每个segment都对应一个Hash表,且都由独立的锁。所以这样就每个线程访问一个Segment,就可以并行访问了,从而提高了效率,这就是锁分段。

JDK1.8之后采用的是和HashMap一样的结构:数组+链表/红黑树

问:JDK1.8ConcurrentHashMap怎样保证线程安全?

使用Synchronized + CAS 的方法来实现线程安全。在用hash定位到数组的头结点时,如果没有发生冲突就用CAS来实现写操作的线程安全,如果发生了冲突,则锁住这个头节点。

java.util.concurrent包还提供了设计用于多线程上下文中的 Collection 实现: ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、CopyOnWriteArrayList 和 CopyOnWriteArraySet。当期望许多线程访问一个给 定 collection 时,ConcurrentHashMap 通常优于同步的 HashMap,ConcurrentSkipListMap 通常优于同步的 TreeMap。当期望的读数和遍历远远 大于列表的更新数时,CopyOnWriteArrayList 优于同步的 ArrayList。下面看看部分用法:

例2

10个线程并发访问这个集合,读取集合数据的同时再往集合中添加数据,运行这段代码会报错,并发修改异常

(1)出现并发修改异常的原因及解决办法

原因:当线程1添加了元素时,modCount+1,并会修改其他线程的expectedModCount+1,而此时线程1中的expectedModCount值为0,虽然modCount不是volatile变量,不保证线程1一定看得到线程2修改后的modCount的值,但是也有可能看得到线程2对modCount的修改,这样就有可能导致线程1中比较expectedModCount和modCount不等,而抛出异常。

解决:

1、将集合创建方式改成:

private static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

这样就不会有并发异常了,因为这个是写入并复制,每次生成新的,所以如果添加操作比较多的话,开销非常大,适合迭代操作比较多的时候使用。

2、在使用iterator迭代的时候使用synchronized或Lock进行同步

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343