ThreadPoolExecutor
1当线程池内线程数小于corePoolSize时,新提交的任务都会创建一个新的线程来执行。
2当线程池内线程数等于corePoolSize时,新提交的任务会放入workQueue中,等待线程池中任务调度。
3当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务。
4当提交任务数超过maximumPoolSize时,新提交任务会交给RejectedExecutionHandler处理。
5当线程池中超过corePoolSize时,空闲时间达到keepAliveTime时,关闭空闲线程。
6当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭 。
LinkedBlockingQueue
1LinkedBlockingQueue内部分别使用的是takeLock和putLock对并发进行控制,也就是说添加和删除并不是互斥操作,可以同时进行,大大地提高了吞吐量。
2LinkedBlockingQueue对每个锁都提供了一个Condition用来挂起和唤醒其它线程。
3put方法
队列已满,阻塞等待。
队列未满,创建一个node放入队列,如果放完还有空间,则唤醒其它线程继续添加。如果放入队列之前没有元素,放完以后要唤醒其它线程进行消费。
offer方法与put方法区别:当队列没有可用元素时:put方法是阻塞等待,offer方法直接返回false。
4take方法
队列为空,阻塞等待。
队列不为空,从队首获取并移除一个元素,如果消费后还有元素在队列中,继续唤醒下一个消费线程进行元素移除。如果放之前队列是满元素,移除完之后要唤醒生产线程进行添加元素。
LinkedBlockingQueue与ArrayBlockingQueue
1队列大小不同 ArrayBlockingQueue是有界的,初始化必须指定大小。而LinkedBlockingQueue可以是有界的也可以是无界的(Integer.MAX_VALUE)。对于后者而言,如果添加速度小于移除速度,在无界时有可能造成内存溢出等问题。
2数据存储容器不同,ArrayBlockingQueue采用的是数组容器,而LinkedBlockingQueue则采用的是以node节点的链表。
3ArrayBlockingQueue使用的数组,所以插入和删除时不会产生额外的对象实例,而LinkedBlockingQueue则会。
4ArrayBlockingQueue添加和删除操作用的是同一个锁,添加和删除互斥。而LinkedBlockingQueue添加和删除操作使用的两个锁,可以同时进行,大大提高了吞吐量。