1、线程池的实现原理?ThreadPoolExecutor参数详解。
(1)线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过就算队列里面有任务,线程池也不会马上执行他们。
(2)当调用execute()方法添加一个任务时,线程池会做如下判断:
a)如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;
b)如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列;
c)如果这时候队列满了,而且正在运行的线程数量小于maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
d)如果队列满了,而且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会抛出异常RejectExecutionExceptiion.
(3) 当一个线程完成任务时,它会从队列中取下一个任务来执行。
(4)当一个线程无事可做,超过一定的时间时,线程池会判断,如果当前运行的核心线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小。
7个参数:corePoolSize核心线程大小、maximumPoolSize最大线程数,keepAliveTime空闲线程存活时间、unit空闲线程存活时间单位、workQueue工作(阻塞)队列、threadFactory线程工厂、handler拒绝策略
2、为什么要同时重写hashcode和equals方法?
hashCode 和 equals 两个方法是用来协同判断两个对象是否相等的,采用这种方式的原因是可以提高程序插入和查询的速度,如果在重写 equals 时,不重写 hashCode,就会导致在某些场景下,例如将两个相等的自定义对象存储在 Set 集合时,就会出现程序执行的异常,为了保证程序的正常执行,所以我们就需要在重写 equals 时,也一并重写 hashCode 方法才行。
3、hashtable、hashmap、currenthashmap有什么区别?
hashtable和hashmap的区别:
.
线程安全
:
HashMap
是非线程安全的,
HashTable
是线程安全的;
HashTable
内部的方法基本
都经过
synchronized
修饰。(如果你要保证线程安全的话就使用
ConcurrentHashMap
);
2.
效率
: 因为线程安全的问题,
HashMap
要比
HashTable
效率高一点。另外,
HashTable
基本被
淘汰,不要在代码中使用它;(如果你要保证线程安全的话就使用
ConcurrentHashMap
);
3.
对
Null key
和
Null value
的支持
:
HashMap
中,
null
可以作为键,这样的键只有一个,可以有
一个或多个键所对应的值为
null
。但是在
HashTable
中
put
进的键值只要有一个
null
,直接抛
NullPointerException
。
4.
初始容量大小和每次扩充容量大小的不同
:
5.
创建时如果不指定容量初始值,
Hashtable
默认的初始大小为
11
,之后每次扩充,容量变为原来
的
2n+1
。
HashMap
默认的初始化大小为
16
。之后每次扩充,容量变为原来的
2
倍。
6.
创建时如果给定了容量初始值,那么
Hashtable
会直接使用你给定的大小,而
HashMap
会将其
扩充为
2
的幂次方大小。也就是说
HashMap
总是使用
2
的幂作为哈希表的大小,后面会介绍到为
什么是
2
的幂次方。
7.
底层数据结构
:
JDK1.8
以后的
HashMap
在解决哈希冲突时有了较大的变化,当链表长度大于阈
值(默认为
8
)时,将链表转化为红黑树,以减少搜索时间。
Hashtable
没有这样的机制。
8.
推荐使用:在
Hashtable
的类注释可以看到,
Hashtable
是保留类不建议使用,推荐在单线程环
境下使用
HashMap
替代,如果需要多线程使用则用
ConcurrentHashMap
替代。
hashmap与currenthashmap的区别:
1. ConcurrentHashMap
对整个桶数组进行了分割分段
(Segment)
,然后在每一个分段上都用
lock
锁
进行保护,相对于
HashTable
的
synchronized
锁的粒度更精细了一些,并发性能更好,而
HashMap
没有锁机制,不是线程安全的。(
JDK1.8
之后
ConcurrentHashMap
启用了一种全新的
方式实现
,
利用
CAS
算法。)
2. HashMap
的键值对允许有
null
,但是
ConCurrentHashMap
都不允许。
currenthashmap与hashtable的区别:
ConcurrentHashMap
和
Hashtable
的区别主要体现在实现线程安全的方式上不同。
底层数据结构
:
JDK1.7
的
ConcurrentHashMap
底层采用
分段的数组
+
链表
实现,
JDK1.8
采用的数据结构跟
HashMap1.8
的结构一样,数组
+
链表
/
红黑二叉树。
Hashtable
和
JDK1.8
之前的
HashMap
的底层数据结构类似都是采用
数组
+
链表
的形式,数组是
HashMap
的主
体,链表则是主要为了解决哈希冲突而存在的;
实现线程安全的方式
:
1.
在
JDK1.7
的时候,
ConcurrentHashMap
(分段锁)
对整个桶数组进行了分割分段
(Segment)
,每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就
不会存在锁竞争,提高并发访问率。(默认分配
16
个
Segment
,比
Hashtable
效率提高
16
倍。)
到了
JDK1.8
的时候已经摒弃了
Segment
的概念,而是直接用
Node
数组
+
链表
+
红黑
树的数据结构来实现,并发控制使用
synchronized
和
CAS
来操作。(
JDK1.6
以后 对
synchronized
锁做了很多优化)
整个看起来就像是优化过且线程安全的
HashMap
,虽然在
JDK1.8
中还能看到
Segment
的数据结构,但是已经简化了属性,只是为了兼容旧版本;
2.
②
Hashtable(
同一把锁
)
:
使用
synchronized
来保证线程安全,效率非常低下。当一个线程
访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用
put
添加
元素,另一个线程不能使用
put
添加元素,也不能使用
get
,竞争会越来越激烈效率越低。
ConcurrentHashMap
结合了
HashMap
和
HashTable
二者的优势。
HashMap
没有考虑同
步,
HashTable
考虑了同步的问题使用了
synchronized
关键字,所以
HashTable
在每次同步执行
时都要锁住整个结构。
ConcurrentHashMap
锁的方式是稍微细粒度的。