在面试中结构化的和面试官聊聊线程安全的集合

版权声明:https://me.csdn.net/weixin_42636552 https://blog.csdn.net/weixin_42636552/article/details/82961713

此案例发生在朋友的一次现场面试中,下面就以面试对话的形式展示出在线程安全的集合这个大的知识点下,面试官一般怎么问。

最后再深入到线程安全的集合


(一)
问:看到你简历里面写到了,阅读过部分集合的源码,那你知道哪些类是线程安全的?

答:Vector是ArrayList的线程安全版本,性能比ArrayList要低,现在已很少使用。Hashtable是线程安全的,现在也很少使用。在jdk1.8之后使用concurrentHashMap这个线程安全的集合比较多。

【期待问一下concurrentHashMap和hashTable的区别,就可以大展拳脚】

(二)
问:除此之外有没有使用过其他线程安全的集合?

答:听过synchronizedMap(Map<K, V> m): 返回指定Map对象对应的线程安全的Map对象。synchronizedSet(Set s): 返回指定Set对象对应的线程安全的Set对象。

【以为到此为止,问问源码什么的】

(三)
问:恩,还不错,那你是怎么知道这些集合的,有没有使用过?

答:。。。。布拉阿布拉。。。

【随便扯就行,尽量变现自己好学,有好奇心】

最后面试官说学习有一个结构会更好,开始不懂原因,后面看来这个知识点,才知道当时的意思。


下面就结构化的看看线程安全的集合

1、以synchronized开头命名的集合

看当多个并发向集合中存、取元素时,就可能会破坏这些集合的数据完整性。
如果程序中有多个线程可能访问以上这些集合,就可以使用Collections提供的类方法把这些集合包装成线程安全的集合。Collections提供了如下几个静态方法。

synchronizedCollection(Collection c): 返回指定collection 对应的线程安全的collection。

synchronizedList(List list): 返回指定List对象对应的线程安全的List 对象。

synchronizedMap(Map<K, V> m): 返回指定Map对象对应的线程安全的Map对象。

synchronizedSet(Set s): 返回指定Set对象对应的线程安全的Set对象。

synchronizedSortedMap(SortedMap<K, V> m): 返回指定SortedMap对象对应的线程安全的SortedMap对象

synchronizedSortedSet(SortedSet s): 返回指定SortedSet对象对应的线程安全的SortedSet对象。

大家都知道synchronized是同步锁,前面有这个单词的集合不用说,内部的资源和synchronized有联系,是安全的。

可以看到,在大家平常使用到的 List, Map, Set, Collection 给前面加上synchronized关键字就可以构成线程安全的集合。

例如需要在多线程里使用线程安全的HashMap对象(如果需要把某个集合包装成线程安全的集合,则应该在创建之后立即包装,如下程序所示),则可以采用如下代码:

 // 使用Collections 的 synchronizedMap 方法将一个普通的HashMap包装成线程安全的类
 HashMap m = Collections.synchronizedMap(new HashMap());

2、以Concurrent 开头命名的集合

从Java 5 开始,在java.util.concurrent 包下提供了大量支持高效并发访问的集合接口和实现类,如下图所示:

在这里插入图片描述

看上图中左边部分

以Concurrent 开头的集合类代表了支持并发访问的集合,它们可以支持多个线程并发写入访问,这些写入线程的所有操作都是线程安全的,但读取操作不必锁定。

以Concurrent 开头的集合类采用了更复杂的算法来保证永远不会锁住整个集合,因此在并发写入时有较好的性能。

以Concurrent 开头的集合类,
ConcurrentHashMap
还有不太常用的:
ConcurrentSkipListMap
ConcurrentSkipListSet
ConcurrentLinkedQueue
ConcurrentLinkedDeque

当多个线程共享访问一个公共集合时,ConcurrentLinkedQueue 是一个恰当的选择。ConcurrentLinkedQueue集合时无需等待。
在默认情况下,ConcurrentHashMap 支持16个线程并发写入,当有超过16 个线程并发向该Map 中写入数据时,可能有一些线程需要等待。实际上,程序通过设置concurrentLevel 构造参数(默认值为16)来支持更多的并发写入线程。
与前面介绍的HashMap 和普通集合不同的是,因为ConcurrentLinkedQueue 和 ConcurrenthashMap 支持多线程并发访问,所以当使用迭代来遍历集合时,该迭代器可能不能反映出创建迭代器之后所做的修改,但程序不会抛出任何异常。

3、以CopyOnWrite 开头的集合

看这张图片右边部分:
在这里插入图片描述

以CopyOnWrite 开头的集合类,如
CopyOnWriteArrayList
CopyOnWriteArraySet。

CopyOnWrite容器即写时复制的容器。
通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。

这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。


一般面试中说出这些分类和各自的理解,面试官会眉开眼笑哦!

猜你喜欢

转载自blog.csdn.net/weixin_42636552/article/details/82961713