线程池的作用:降低资源消耗,提高响应速度,提高线程的可管理性
ThreadPoolExecutor是java.util.concurrent包
线程池参数: corePoolSize:线程池的核心线程数
maximumPoolSize:线程池允许的最大线程数;
keepAliveTime: 指的是空闲线程结束的超时时间;
unit :是一个枚举,表示 keepAliveTime 的单位;
workQueue:表示存放任务的BlockingQueue<Runnable>队列;
ThreadFactory:用来创建线程的工厂,new ThreadFactoryBuilder().setNameFormat("当前线程-%d").build();
handler: 线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务。
a、ThreadPoolExecutor.AbortPolicy:直接抛出RejectedExecutionException异常,丢弃任务,阻止系统正常工作。(Executors类创建线程池的默认丢弃策略);
b、ThreadPoolExecutor.CallerRunsPolicy:只要线程池未关闭,直接去调用线程池的线程中处理该任务,可能引起性能的急剧下降;
c、ThreadPoolExecutor.DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
d、ThreadPoolExecutor.DiscardPolicy:偷偷的丢弃任务,但是不抛出异常;
e、当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。
workQueue: SynchronousQueue(没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加新的元素),LinkedBlockingQueue(相当于无界,长度是Integer.MAX_VALUE),ArrayBlockingQueue(有界的,可以自己指定长度)
线程池的工作流程是什么?
1、如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务
2、如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列
3、如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务
4、如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常RejectExecutionException
注意:当一个线程完成任务时,它会从队列中取下一个任务来执行。
当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
线程池的状态有哪些?
Running、ShutDown、Stop、Tidying、Terminated
线程池最常用的提交任务的方法有两种:
execute: 没有返回值;
submit: 方便进行Exception处理,由于返回参数是future,如果执行期间抛出了异常,可以使用future.get()进行捕获。
线程池的种类:newSingleThreadExecutor,newFixedThreadPool,newCachedThreadPool,newScheduledThreadPool;