一、为什么使用线程池?
线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。
使用线程池的好处:
- 降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。 当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性。 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
二、线程池的核心参数
- corePoolSize : 核心线程大小。线程池一直运行,核心线程就不会停止。
- maximumPoolSize :线程池最大线程数量。非核心线程数量=maximumPoolSize-corePoolSize
- keepAliveTime :非核心线程的心跳时间。如果非核心线程在keepAliveTime内没有运行任务,非核心线程会消亡。
- workQueue :阻塞队列。ArrayBlockingQueue,LinkedBlockingQueue等,用来存放线程任务。
- defaultHandler :饱和策略。ThreadPoolExecutor类中一共有4种饱和策略。通过实现RejectedExecutionHandler接口。
- AbortPolicy : 线程任务丢弃报错。默认饱和策略。
- DiscardPolicy : 线程任务直接丢弃不报错。
- DiscardOldestPolicy : 将workQueue队首任务丢弃,将最新线程任务重新加入队列执行。
- CallerRunsPolicy :线程池之外的线程直接调用run方法执行。
- ThreadFactory :线程工厂。新建线程工厂。
三、线程池执行任务的流程
1. 线程池执行execute/submit方法向线程池添加任务,当任务小于核心线程数corePoolSize,线程池中可以创建新的线程。
2. 当任务大于核心线程数corePoolSize,就向阻塞队列添加任务。
3. 如果阻塞队列已满,需要通过比较参数maximumPoolSize,在线程池创建新的线程,当线程数量大于maximumPoolSize,说明当前设置线程池中线程已经处理不了了,就会执行饱和策略。
四、Java中的线程池
newCachedThreadPool:创建一个数目无上限,但是线程不会轻易销毁的线程池,初始情况下,线程池里面没有线程,随着注册任务进去,就会创建一些线程来处理任务,任务完成之后,线程不会立刻销毁,而是仍然在等待执行新的任务
newFixedEhreadPool:创建一个固定大小的线程池(线程数目是固定的),不管任务有多少,线程的数目不会增加,任务就在阻塞队列中排队。【工作中最常使用的线程池】