1.HashMap 和 Hashtable 区别
Hashtable 从类名就可以看出是个古老的类,不允许null作为key或者value。加锁的方式保证线程安全,底层使用互斥锁,性能很低,不推荐使用
2.HashMap与ConcurrentHashMap有什么区别?
HashMap是非线程安全的,这意味着不应该在多线程中对这些Map进行修改操作,否则会产生数据不一致的问题,甚至还会因为并发插入元素而导致链表成环。查找的时候造成死循环,影响整个应用程序
Collections工具类可以将一个Map转换成线程安全的实现,是通过一个包装类把所有功能都委托给传入的Map, 包装类是用synchronized关键字保证线程安全的
ConcurrentHashMap底层实现比较复杂,性能也要高上很多。他减小了锁的粒度,没有用一个全局锁锁住自己。而且只有修改、插入的时候才有锁,检索操作是不需要锁的。
3.说一说你对LinkedHashMap的理解?
LinkedHashMap使用双向链表来维护key-value对的顺序,该链表负责维护Map的迭代顺序,迭代顺序与key-value对的插入顺序保持一致
4.说一说你对TreeMap的理解?
TreeMap基于红黑树实现。根据其键的自然顺序进行排序,或者根据创建Map时提供的 Comparator 进行排序,具体取决于使用的构造方法。 TreeMap的基本操作containsKey、get、put、remove floorKey,ceilingKey,firstKey方法,它的时间复杂度是log(N)。 TreeMap包含几个重要的成员变量:root、size、comparator 其中root是红黑树的根节点。它是Entry类型,Entry是红黑树的节点,它包含了红黑树的6个基本组成:key、value、left、right、parent和color
5.Map和Set区别、List和Set区别、ArrayList和LinkedList区别
略
6.介绍下ArrayList数据结构?
数组,初始创建容量10,超过限制扩展50%的容量,System.arraycopy() ,优缺点和数组一样。 ArrayList的底层是用数组来实现的,默认第一次插入元素时创建大小为10的数组,超出限制时会增加50%的容量,并且数据以 System.arraycopy() 复制到新的数组,因此最好能给出数组大小的预估值。 按数组下标访问元素的性能很高,这是数组的基本优势。直接在数组末尾加入元素的性能也高,但如果按下标插入、删除元素,则要用 System.arraycopy() 来移动部分受影响的元素,性能就变差了,这是基本劣势。
7.有哪些线程安全的List?
- Vector: 古老API效率低
- Collections.SynchronizedList, 可以把不安全的List 包装成一个安全的List
- CopyOnWriteArrayList,读的时候不加锁,写的时候采用复制底层数组的方式来实现写操作,写的时候是有锁的
8.谈谈CopyOnWriteArrayList的原理
CopyOnWriteArrayList是Java.util.concurrent包提供的并发类, 读的时候是无锁的,写的时候是会把数据进行一个拷贝,然后再新的数组里写,再把原来的引用指向新数组。这样在写的时候,如果有读的操作,会读之前老副本。因此上锁的写操作不会影响并发的读访问。
因此CopyOnWriteArrayList读性能很高,无需任何同步措施,适用于读多写少的并发场景。 传统的ArrayList在遍历的时候进行修改,会出现ConcurrentModificationException,CopyOnWriteArrayList就不会出现这个问题。 但是缺点也很明显,就是内存占用问题, 每次写都拷贝,数据量大的时候,内存压力大,可能频繁需要GC。 还有个缺点就是无法保证及时性,读的是就的数据,不是强一致性的。
9.说一说TreeSet和HashSet的区别
HashSet、TreeSet中的元素都是不能重复的,都是线程不安全的 HashSet 能放null, TreeSet不能 TreeSet能按自然排序或者自定义排序,HashSet无序 HashSet底层是HashMap,value存了一个PRESENT,是静态的Object对象,TreeSet底层是红黑树
10.BlockingQueue中有哪些方法,为什么这样设计?
抛异常:如果操作无法立即执行,则抛一个异常; 特定值:如果操作无法立即执行,则返回一个特定的值(一般是 true / false)。 阻塞:如果操作无法立即执行,则该方法调用将会发生阻塞,直到能够执行; 超时:如果操作无法立即执行,则该方法调用将会发生阻塞,直到能够执行。但等待时间不会超过给定值,并返回一个特定值以告知该操作是否成功(典型的是true / false)。
|