1.线程池参数
2.线程池执行流程
2.1 流程图
2.2 线程创建的流程
当任务提交之后,线程池首先会检查当前线程数,如果当前的线程数小于核心线程数(corePoolSize),比如最开始创建的时候线程数为 0,则新建线程并执行任务。
当提交的任务不断增加,创建的线程数等于核心线程数(corePoolSize),新增的任务会被添加到 workQueue 任务队列中,等待核心线程执行完当前任务后,重新从 workQueue 中获取任务执行。
假设任务非常多,达到了 workQueue 的最大容量,但是当前线程数小于最大线程数(maximumPoolSize),线程池会在核心线程数(corePoolSize)的基础上继续创建线程来执行任务。
假设任务继续增加,线程池的线程数达到最大线程数(maximumPoolSize),如果任务继续增加,这个时候线程池就会采用拒绝策略来拒绝这些任务。
2.3 小结
在任务不断增加的过程中,线程池会逐一判断
核心线程数(corePoolSize)
任务队列(workQueue)
最大线程数(maximumPoolSize)
拒绝策略
3.核心线程数和最大线程数
corePoolSize 是核心线程数,初始大小是 0,但是在创建线程之后,核心线程会常驻在线程池中,即使没有任务执行,也不会被销毁。随着任务数的增加,当任务队列(workQueue )满了之后,线程池根据最大线程数(maximumPoolSize)来创建非核心线程,当任务执行完,线程有空闲,非核心线程会被回收。
“正式员工” 与 “外包员工”
一般大型银行会有很多项目要做,但是银行的正式编制有限,这种时候就需要采用“人力外包”的形式。corePoolSize 相当于正式员工,而 (maximumPoolSize - corePoolSize) 相当于外包员工,当项目比较少的时候,正式员工就可以处理,但是项目增多时超过了处理负荷,就需要增加外包人员协助进行处理。
当项目完成或者结束之后,正式员工还是在银行上班,等待任务或者处理新的任务,而外包人员则会结束和银行的合同。
4.keepAliveTime+时间单位
第三个参数是 keepAliveTime + 时间单位,当线程池中线程数量多于核心线程数时,而此时又没有任务可做,线程池就会检测线程的 keepAliveTime,如果超过规定的时间,无事可做的线程就会被销毁,以便减少内存的占用和资源消耗。如果后期任务又多了起来,线程池也会根据规则重新创建线程,所以这是一个可伸缩的过程,比较灵活,我们也可以用 setKeepAliveTime 方法动态改变 keepAliveTime 的参数值。
5.ThreadFactory
ThreadFactory 使用的是抽象工厂模式
第四个参数是 ThreadFactory,ThreadFactory 实际上是一个线程工厂,它的作用是生产线程以便执行任务。我们可以选择使用默认的线程工厂,创建的线程都会在同一个线程组,并拥有一样的优先级,且都不是守护线程,我们也可以选择自己定制线程工厂,以方便给线程自定义命名,不同的线程池内的线程通常会根据具体业务来定制不同的线程名。
为什么创建的线程不是守护线程?
守护线程:和主线程一起结束的线程,叫守护线程。
非守护线程:主线程的结束不影响线程的执行的线程,也叫用户线程。
源码如下:
public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon())// 判断是否是守护线程 t.setDaemon(false);// 如果是则设置为 false if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY);// 设置优先级为 5 return t; }
有源码可知,如果线程是守护线程,会重新设置为非守护线程,而设置为非守护线程的原因是保证该线程不受主线程的影响。
6.workQueue 阻塞队列
阻塞队列,后续专题章节进行讲解:线程池常用的阻塞队列有哪些
7.Handler 拒绝策略
拒绝策略,后续专题章节进行讲解:线程池的4种拒绝策略
参考文献
版权声明:本文为CSDN博主「不懂的浪漫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiewenfeng520/article/details/106954170/