JAVA多线程常问面试题(自答版)

63 阅读4分钟

1.Collection和Collections的区别

Collection是一个集合接口,提供了对集合对象进行基本操作的通用接口方法

Collections是集合类的一个工具类,提供了一系列静态方法,用于对集合中元素进行排序,搜索以及线程安全等各种操作

2.JAVA容器都有哪些

List:Vector,ArrayList,LinkedList,CopyOnWriteArrayList

Queue:PriorityQueue

Set:HashSet,TreeSet

Map:HashMap,TreeMap,ConcurrentHashMap

3.常见数据结构的原理

List篇:

Vector:内部通过数组实现,支持线程的同步,某一时刻只能有一个线程能够写Vector,因此它是线程安全的,但访问慢

ArrayList:最常用的List实现类,内部通过数组实现,默认大小为10,当数组大小不足时会触发扩容机制,通过Arraylist.ensureCapacity()扩容出新数组,新数组大概在原数组大小的1.5倍左右,然后会通过Array.copyOf()方法将原数组内容拷贝过去

LinkedList:用双向链表储存数据,适合数据的动态插入和删除,访问数据很慢(时间复杂度O(n)),适合写多读少的场景

CopyOnWriteArrayList:写时复制,当加入元素时不会直接在原数组操作,而是新复制一份数组,在新数组进行操作,再将原数组指向新数组,因此是线程安全的,但是每次写入都会复制数组,开销比较大,建议对需添加的元素累计后批量加入

Queue篇:队列是先进先出的数据结构,只允许在表的一端进行获取操作,另一端进行插入操作,此FIFO特性和阻塞特点常用于作为Buffer(缓冲区)

Map篇:

HashMap:内部通过数组+链表+红黑树(JDK8之后)实现,通过Key-Value键值对作为储存元素实现的哈希结构,将Key通过哈希函数计算后得到HashCode,该HashCode作为下标找到数组的相应位置,将储存元素存入,因此是无序的,由于哈希函数计算可能会出现不同Key计算出同一HashCode的情况,所以在数组同一位置会出现冲突,这时候会在当前位置形成链表,在JDK8之后为尾插法,避免死链,当链表元素超过8的时候,链表会转为红黑树,目的是更快地查询(红黑树时间复杂度为O(logn),链表为O(n)),HashMap默认大小为16,并且容量设定为,方便计算落槽位置

TreeMap:内部由红黑树实现,与HashMap不同的是它是可排序的,实现SortedMap接口,根据键排序

ConcurrentHashMap:在JDK8之前为分段锁,JDK8之后与HashMap基本一致,是数组+链表+红黑树的结构,通过CAS,synchronized加锁,因此是线程安全的,在并发情况下更推荐用ConcurrentHashMap代替HashMap,并且性能不会减少太多

Set篇:

HashSet:使用HashMap实现,其中储存元素放在HashMap的Key上,Value统一为PRESENT,由于Key不能重复,所以HashSet是不允许有重复元素的

TreeSet:使用TreeMap实现,底层为树结构,按某种比较规则插入合适位置,保证有序

4.树结构的特点

一个节点,即使只有根节点,也是一棵树

任何一个节点和下面所有节点构成的树称为子树

根节点没有父节点,叶子节点没有子节点

除根节点外,任何节点有且只有一个父节点

任何节点可以有n个子节点

5.平衡二叉树

树的高度差不能超过1

6.AVL树是什么

AVL树是一种平衡二叉树查找树,增删节点后通过旋转重新达到平衡

7.红黑树的特点是什么

节点只能是红色和黑色

根节点必须是黑色

所有NIL节点(Nothing In Leaf,叶子节点上不存在的两个虚拟节点)都是黑色

同一路径不能出现相邻的两个红色节点

每条路径上黑色节点数目要相同

8.什么是fail-fast机制

fail-fast是集合常见的错误检测机制,常发生在多线程遍历集合元素的过程中,在遍历途中,其他线程对集合进行了修改,就会触发fail-fast机制,在进入遍历前,会将实时修改次数modCount赋值给expectedModCount(一个计数比较器),当数据不相等时抛出异常