JUC高并发编程
十一、ThreadPool 线程池
11.1)线程池简介
线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销, 进而影响缓存局部性和整体性能;而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务;这避免了在处理短时间任务时创建与销毁线程的代价。
程池不仅能够保证内核的充分利用,还能防止过分调度。
11.1.1)线程池简介
线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量, 超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。
11.1.2)线程池特点
线程池的主要特点为:
-
降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的销耗;
-
提高响应速度:当任务到达时,任务可以不需要等待线程创建就能立即执行;
-
提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会销耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控;
-
Java 中的线程池是通过 Executor 框架实现的,该框架中用到了 Executor,Executors, ExecutorService,ThreadPoolExecutor这几个类 ,其关系如下图:
11.2)线程池参数说明
常用参数:
-
corePoolSize:线程池的常驻线程数量(核心)
-
maximumPoolSize:线程池能容纳的最大线程数
-
keepAliveTime空闲:线程存活时间
-
unit :线程存活的时间单位
-
BlockingQueue<Runnable> workQueue :存放提交但未执行任务的队列 【阻塞队列】
-
threadFactory: 创建线程的工厂类【线程工厂】
-
handler :等待队列满后的拒绝策略
线程池中,有三个重要的参数,决定影响了拒绝策略:
corePoolSize - 核心线程数,也即最小的线程数;
workQueue - 阻塞队列;
maximumPoolSize - 最大线程数
当提交任务数大于 corePoolSize 的时候,会优先将任务放到 workQueue 阻塞队列中;当阻塞队列饱和后,会扩充线程池中线程数,直到达到 maximumPoolSize 最大线程数配置。此时再多余的任务,则会触发线程池的拒绝策略。
总结:当提交的任务数大于(workQueue.size() + maximumPoolSize ),就会触发线程池的拒绝策略
11.3)线程池底层工作原理
线程池底层工作原理如下图所示:
线程池底层工作流程:
-
在创建了线程池后,线程池中的线程数为零;
-
当调用execute()方法添加一个请求任务时,线程池会做出如下判断:
2.1) 如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行