线程池ThreadPoolExcutor执行流程你弄清楚了么

ThreadPoolExcutor的核心参数

首先来回忆下线程池的几个核心参数;

  1. corePoolSize:核心线程数
  2. maximumPoolSize:最大线程数
  3. keepAliveTime:线程空闲时间
  4. TimeUnit:时间单位
  5. workQueue:线程工作队列
  6. ThreadFactory:线程创建工厂
  7. RejectedExecutionHandler:线程拒绝策略

这些也是我们日常使用线程池,所需要关注的一些参数配置,具体配置的大小,需要根据我们实际服务器的实际情况,这里就做简单了解下,就不过多于纠结了,分为两种情况:

  • IO密集型配置线程数经验值是:2N,其中N代表CPU核数。
  • CPU密集型配置线程数经验值是:N + 1,其中N代表CPU核数。

ThreadPoolExcutor线程池的线程数执行情况

我们通过配置线程池的参数,结合提交的任务数,来去观察任务数、核心线程数、最大线程数和队列之间的变化;

创建线程池

ini 复制代码
public class ThreadPoolTest {
    public static void main(String[] args) {
        //定义一个线程池 核心线程数为4,最大线程数为6,队列长度为2
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor poolExecutor =new ThreadPoolExecutor(4,6,0L, TimeUnit.MILLISECONDS
        ,workQueue);
        // 任务数 3-9
        int work =9;
        for (int i = 1; i <= work; i++) {
            int workCount =i;
            poolExecutor.submit(new Runnable() {
                @Override
                public void run() {
//                    Thread thread =Thread.currentThread();
//                    String threadName =thread.getName();
//                    int activeCount = poolExecutor.getActiveCount();
//                    System.out.println("当前任务:"+workCount+",线程名称"+threadName+",活跃线程数:"+activeCount);
                    System.out.println(Thread.currentThread().getName());
                    try{
                        Thread.sleep(300000L);
                    }catch (InterruptedException ex){
                        ex.printStackTrace();
                    }
                }
            });
            System.out.println("当前任务:"+workCount+",创建第" + i + "个线程后, 线程池情况:" + poolExecutor.toString());
        }     
    }
}

执行结果:

  • 第一种情况:任务数为3,核心线程数为4,最大线程数为6; 任务数<核心线程数; 执行main方法,可以得到活跃的线程数为3个线程
  • 第二种情况:任务数为4,核心线程数为4,最大线程数为6;任务数=核心线程数; 执行main方法,可以得到活跃线程为4;
  • 第三种情况:任务数为5,核心线程数为4,最大线程数为6;任务数>核心线程数,<最大线程数6,会将多出来1个的任务放入在队列等待; 执行main方法,相当于任务数 <核心线程数4+队列长度2, 可以得到活跃线程为4;
  • 第四种情况:任务数为6,核心线程数为4,最大线程数为6;任务数 =核心线程数,=最大线程数6,会将多出来的任务放入在队列等待; 执行main方法,相当于任务数 =核心线程数4+队列长度2, 可以得到活跃线程为4;
  • 第五种情况:任务数为7,核心线程数为4,最大线程数为6;任务数 >核心线程数,>最大线程数6; 执行main方法,相当于任务数 <最大线程数6+队列长度2, 此时任务数为7,线程池会开启4个核心线程执行4个任务,2个任务放入队列等待,此还有一个任务没有执行,但是小于最大线程数6,会再开启一个活跃线程去执行这1一个任务,所以总共活跃线程就是5;
  • 第六种情况:任务数为8,核心线程数为4,最大线程数为6;任务数 =最大核心线程数6+队列2;活跃线程数就是6;
  • 第七种情况:任务数为9,核心线程数为4,最大线程数为6;任务数 >最大核心线程数6+队列2;可以看到在执行到第8个任务的时候,活跃线程数为6,等待队列任务为2,执行到第9个任务的时候,由于任务数 9 >最大核心线程数6+队列2,所以触发了拒绝策略;

总结

在正常情况下,线程池内活跃线程数>核心线程数时,后面进来的任务会加入队列中等待,如果队列已满,会新建线程直到线程池内线程数等于最大线程数,如果还有新的任务进行提交,那么将会触发默认的拒绝策略,AbortPolicy 拒绝创建;

相关推荐
黄交大彭于晏5 分钟前
发送文件脚本源码版本
java·linux·windows
钮钴禄·爱因斯晨11 分钟前
Java 面向对象进阶之多态:从概念到实践的深度解析
java·开发语言·数据结构
鸽子炖汤11 分钟前
Java中==和equals的区别
java·开发语言·jvm
hstar952730 分钟前
二、即时通讯系统设计经验
java·架构
江梦寻44 分钟前
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
开发语言·后端·python·macos·架构·策略模式
风象南1 小时前
SpringBoot的4种死信队列处理方式
java·spring boot·后端
互联网全栈架构2 小时前
遨游Spring AI:第一盘菜Hello World
java·人工智能·后端·spring
优秀的颜3 小时前
计算机基础知识(第五篇)
java·开发语言·分布式
BillKu3 小时前
Java严格模式withResolverStyle解析日期错误及解决方案
java
网安INF3 小时前
ElGamal加密算法:离散对数难题的安全基石
java·网络安全·密码学