参考:线程池 ThreadPoolExecutor 源码详细分析
JDK Excutor框架熟悉
ThreadPoolExecutor 继承体系
在 Java 中,如果每个请求到达就创建一个新线程
,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。
如果在一个 Jvm 里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。
线程池初始化时是没有创建线程的
,线程池里的线程的初始化与其他线程一样,但是在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。这样既节省了建立线程所造成的性能损耗,也可以让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。
为了解决这个问题,就有了线程池的概念,线程池的核心逻辑是提前创建好若干个线程放在一个容器中。如果有任务
需要处理,则将任务直接分配给线程池中的线程来执行就行,任务处理完以后这个线程不会被销毁,而是等待后续分配任务。
同时通过线程池来重复管理线程还可以避免创建大量线程增加开销。
public ThreadPoolExecutor(int corePoolSize, //核心线程数量
int maximumPoolSize, //最大线程数
long keepAliveTime, //超时时间,超出核心线程数量以外的线程空余存活时间
TimeUnit unit, //存活时间单位
BlockingQueue<Runnable> workQueue, //保存执行任务的队列
ThreadFactory threadFactory,//创建新线程使用的工厂
RejectedExecutionHandler handler //当任务无法执行的时候的处理方式)
线程池的核心属性参数
线程池的生命周期
代码实例:线程池ThreadPoolExecutor的核心线程数,最大线程数,队列长度的关系?
实现:ThreadPoolExecutor创建线程池使用
代码:
public static void main(String[] args) {
// 创建线程池 , 参数含义 :(核心线程数,最大线程数,存活时间,时间单位,任务队列长度)
ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 8,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(2));
//设置a的值范围在:a = (corePoolSize-1) ~ (max+queue+1) ,分析:任务数 与 活跃线程数,核心线程数,队列长度,最大线程数的关系。
int a = 10;
for (int i = 1; i <= a; i++) {
int j = i;
pool.submit(new Runnable() {
@Override
public void run() {
//获取线程名称
Thread thread = Thread.currentThread();
String name = thread.getName();
//输出
int activeCount = pool.getActiveCount();
System.out.println("任务:"+j+"-----,线程名称:"+name+"-----活跃线程数:"+activeCount);
}
});
}
//关闭线程池
pool.shutdown();
}
总 结 : \color{red}{总结:} 总结:
- 1、随着任务数量的增加,会增加活跃的线程数。
- 2、当活跃的线程数 = 核心线程数,此时不再增加活跃线程数,而是往任务队列里堆积。
- 3、当任务队列堆满了,随着任务数量的增加,会在核心线程数的基础上加开线程
- 4、直到活跃线程数 = 最大线程数,就不能增加线程了。
- 5、如果此时任务还在增加,则: 任务数11 > 最大线程数8 + 队列长度2 ,抛出异常RejectedExecutionException,拒绝任务。
输出:
//任务数 a = 4 , 活跃线程数4 , 任务数 < 核心线程数。
//任务数 a = 5 , 活跃线程数5 , 任务数 = 核心线程数。
//任务数 a = 6 , 活跃线程数5 , 任务数 < 核心线程数5 + 队列长度2 。
//任务数 a = 7 , 活跃线程数5 , 任务数 = 核心线程数5 + 队列长度2 。
//任务数 a = 8 , 活跃线程数6 , 任务数 < 最大线程数8 + 队列长度2 . 活跃线程数是在核心线程数5的基础上.加1个活跃线程。
//任务数 a = 9 , 活跃线程数7 , 任务数 < 最大线程数8 + 队列长度2. 活跃线程数是在核心线程数5的基础上.加2个活跃线程。
//任务数 a = 10 , 活跃线程数8 , 任务数 = 最大线程数8 + 队列长度2. 活跃线程数是在核心线程数5的基础上.加3个活跃线程。
//任务数 a = 11 , 活跃线程数8 , 任务数 > 最大线程数8 + 队列长度2 。抛出异常RejectedExecutionException
自己的输出: