public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
参数含义
- corePoolSize :表示线程池中核心线程数
- maximumPoolSize :表示线程池中能创建的最大线程数
- keepAliveTime :表示空闲线程的存活时间
- TimeUnit unit :表示keepAliveTime的单位
- workQueue:用于缓存任务的阻塞队列
- threadFactory :指定创建线程的工厂
- handler:饱和策略(拒绝策略)
工作原理
如果有空闲线程,则直接执行该任务;
如果没有空闲线程,且当前运行的线程数少于corePoolSize,则创建新的线程执行该任务;
如果没有空闲线程,且当前的线程数等于corePoolSize,同时阻塞队列未满,则将任务放入阻塞队列,而不添加新的线程;
如果没有空闲线程,且阻塞队列已满,同时线程池中的线程数小于maximumPoolSize ,则创建新的线程执行任务;
如果没有空闲线程,且阻塞队列已满,同时池中的线程数等于maximumPoolSize ,则根据构造函数中的 handler 指定的策略来拒绝新的任务。
阻塞队列
SynchronousQueue
(1)没有容量大小,即无缓冲的阻塞队列;
(2)每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态;
(3)底层实现有两种
非公平的堆栈,遵循先进后出,每次从栈顶取元素;
公平的队列,遵循先进先出,每次从队列头取元素。
(4)使用CAS实现线程的安全访问
Executors.newCachedThreadPool 使用了这个队列。
ArrayBlockingQueue
(1)内部维护了一个定长数组,在初始化的时候,必须传入一个容量大小的值;
(2)生产者和消费者使用的是同一把锁ReentrantLock,使用公平锁还是非公平锁,在创建ArrayBlockingQueue时可以指定,默认是非公平锁。
(3)当队列为空,消费者线程被阻塞;当队列装满,生产者线程被阻塞;使用Condition的方法来同步和通信:await()和signal()
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
LinkedBlockingQueue
(1)内部维护的是一个链表结构。在生产和消费的时候,需要创建Node对象进行插入或移除,大批量数据的系统中,其对于GC的压力会比较大。
(2)LinkedBlockingQueue有默认的容量大小为:Integer.MAX_VALUE,也可以传入参数指定容量大小
(3)LinkedBlockingQueue中的锁是分离的,生产者的锁PutLock,消费者的锁takeLock。在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。
(4)put方法将一个对象放到队列尾部,在队列满的时候会阻塞直到有队列成员被消费,take方法从head取一个对象,在队列为空的时候会阻塞,直到有队列成员被放进来。
DelayedWorkQueue
(1)通过数组实现的堆来存储任务
(2)ScheduledThreadPoolExecutor阻塞队列使用的都是DelayedWorkQueue;
(3)可以延迟执行任务,比如说一定时间后执行任务或是每隔一定的时间执行一次任务。
PriorityBlockingQueue
(1)按照优先级进行内部元素排序的无界阻塞队列。队列中的元素必须实现 Comparable 接口,通过实现compareTo()方法进行排序。优先级最高的元素始终排在队列的头部;
(2)通过ReentrantLock来保证线程并发安全,内部控制线程同步采用公平锁。
(3)内部使用二叉树堆维护元素优先级,使用数组作为元素存储的数据结构,数组是可扩容的。
饱和策略,拒绝策略
handler,当 workQueue 已满,且池中的线程数达到 maximumPoolSize 时,线程池拒绝添加新任务时采取的策略。(可以不指定)
hreadPoolExecutor.AbortPolicy()
丢弃任务,并抛出RejectedExecutionException异常,默认策略。
ThreadPoolExecutor.DiscardPolicy()
丢弃任务,但是不抛出异常。
ThreadPoolExecutor.CallerRunsPolicy()
由向线程池提交任务的线程来执行该任务
ThreadPoolExecutor.DiscardOldestPolicy()
抛弃最旧的任务(最先提交而没有得到执行的任务)
线程池的关闭
关闭线程池,可以通过shutdown和shutdownNow两个方法
原理:遍历线程池中的所有线程,然后依次中断
1、shutdownNow首先将线程池的状态设置为STOP,然后尝试停
止所有的正在执行和未执行任务的线程,并返回等待执行任务的
列表;
2、shutdown只是将线程池的状态设置为SHUTDOWN状态,然
后中断所有没有正在执行任务的线程。