我们以提问的方式学习线程池,更容易理解掌握线程池的使用。
1.什么是线程池?为什么要使用线程池?
1.减少开销,因为线程的创建和销毁,都需要开销。
2.提高响应速度:假如创建线程时间T1,执行时间T2,销毁线程时间T3,免去T1和T3的时间。
3.提高线程的可管理性。
线程池ThreadPoolExecutor
JDK所有线程池实现的父类
ThreadPoolExecutor的构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
各个参数的含义:
corePoolSize:线程池中核心线程数。
maximumPoolSize:线程池允许的最大线程数。
keepAliveTime:线程空闲下来后,存活的时间,这个参数只在
> corePoolSize才有用。
unit:存活时间的单位值。
workQueue:保存任务的阻塞队列。
ThreadFactory:创建线程的工厂,给新创建的线程赋予名字。
RejectedExecutionHandler :饱和策略。
AbortPolicy :直接抛出异常,默认;
CallerRunsPolicy:用调用者所在的线程来执行任务
DiscardOldestPolicy:丢弃阻塞队列里最老的任务,队列里最靠前的任务
DiscardPolicy :当前任务直接丢弃
实现自己的饱和策略,实现RejectedExecutionHandler接口即可。
poolSize:线程池中的线程数
请介绍下ThreadPoolExecutor的工作流程?
图片来自Mark老师
当新提交一个任务时:
如果poolSize < corePoolSize时,就会新增一个线程执行该任务;
如果poolSize = corePoolSize时,就会把任务放入到workQueue阻塞队列中;
如果 maximumPoolSize > poolSize > corePoolSize时,此时workQueue阻塞队列已满时,就会新增一个线程;
如果poolSize = maximumPoolSize时,此时workQueue阻塞队列已满,就会根据饱和策略RejectedExecutionHandler 拒绝新任务。