在一个应用程序中,需要多次使用线程,也就是需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。所以便于管理线程,线程池就诞生啦。
ThreadPoolExecutor
ThreadPoolExecutor的构造函数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize:指定线程池中的线程数量,它的数量决定了添加的任务是开辟新的线程去执行,还是放到workQueue任务队列中去。
maximumPoolSize:指定线程池中的最大线程数量。
keepAliveTime:当线程池中空闲线程数量超过corePoolSize时,多余线程会在多长时间内被销毁。
unit:keepAliveTime的单位
workQueue:任务队列,被增加到线程池中,但还未被执行的任务。分为直接提交队列,有界任务队列、无界任务队列、优先人物队列
threadFactory:线程工厂,用于创建线程
handle:拒绝策略
放张图来理解下。
一、workQueue任务队列
1.直接提交队列: SynchronousQueue,一个特殊的BlockingQueue,提交的任务不会被缓存,每执行一个插入操作就会阻塞,需要再执行一个删除操作才会被唤醒。
2.有界的任务队列: ArrayBlockingQueue,基于数组
3.无界的任务队列:LinkedBlockingQueue,基于链表
4.优先任务队列:PriorityBlockingQueue,按照优先级进行内部元素排序的无限队列。
无限队列就是任务池中的任务队列可以无限制的增加新的任务,而线程池创建的最大数量就是corePoolSize设置的数量,在这种情况下maximumPoolSize这个参数是无效的。即使任务队列中缓存了很多未执行的任务,当线程池线程数量达到corePoolSize后就不会增加了。
Blocking:当队列满了,便会阻塞等待,直到有元素出队,后续的元素才可以被加入队列。
二、拒绝策略
1.AbortPolicy策略:直接抛出异常,阻止系统正常工作。
2.CallerRunsPolicy:直接调用execute来执行当前任务。
3.DisCardPolicy:不执行新任务,也不抛出异常,不做任何处理。
4.DisCardOldestPolicy:丢弃任务队列中最老的一个任务,也就是当前任务队列中最先被添加进去的,马上要被执行的那个任务,并尝试再次提交。
三、四种常见的线程池:
1.CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
2.SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
3.SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
4.FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程。