首页 > 编程语言 > 详细

线程池任务增长过程分析

时间:2019-02-12 18:43:06      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:system   意义   exec   exe   ise   核心线程   fin   private   throws   

线程池配置参数如下:

    //线程缓冲队列
    private static BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(10);
    // 核心线程数
    private static final int SIZE_CORE_POOL = 5;
    // 线程池维护线程的最大数量
    private static final int SIZE_MAX_POOL = 9;
    // 线程池维护线程所允许的空闲时间
    private static final long ALIVE_TIME = 2000;
    //创建线程池
    private static ThreadPoolExecutor pool = new ThreadPoolExecutor(SIZE_CORE_POOL, SIZE_MAX_POOL, ALIVE_TIME, TimeUnit.MILLISECONDS, bqueue, new ThreadPoolExecutor.CallerRunsPolicy());
    static {
        //这个方法一调用,会让线程池立即初始化核心线程数相等数量的线程,如果不调用,初始线程数就是0,当有任务来的时候才会创建线程
        pool.prestartAllCoreThreads();
    }

ThreadPoolExecutor构造函数的参数意义不再多说,按照上面的参数配置,说明一下执行20个任务且每个任务执行时间1秒,线程池中的线程和队列变化过程:
由于调用了prestartAllCoreThreads这个方法,线程池初始线程5个,添加前五个任务会分别占用一个线程执行,第六个任务开始会被放到bqueue队列中,队列长度是10所以到第15个任务的时候核心线程被占用,队列也满了,第16个任务就会创建新的线程执行,这些任务不经过队列排队所以会在队列中任务之前执行,直到第19个任务线程数达到SIZE_MAX_POOL大小数量9,不再创建线程,第20个任务就会按照阻塞策略执行,CallerRunsPolicy这个策略的意思就是在调用者线程中直接执行任务,也是不经过排队,效果和前面创建线程执行一样,随着任务被执行,队列中的任务被消费掉队列的长度也会恢复到0,空闲线程空闲时间超过2秒线程会关闭,最后保留5个线程存活,用一个main方法进行验证:

    public static void main(String[] args) throws InterruptedException {
        for (int i = 1; i <= 20; i++) {
            System.out.println("线程池线程数:" + pool.getPoolSize() + ",队列长度" + pool.getQueue().size());
            System.out.println("调用第" + i + "个任务");
            final int a = i;
            pool.execute(new Runnable() {

                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("完成第" + a + "个任务");
                }
            });
        }
        System.out.println("任务调用完成");
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            Thread.sleep(1000);
            System.out.println("线程池线程数:" + pool.getPoolSize() + ",队列长度" + pool.getQueue().size());
        }
    }

执行结果:

线程池线程数:5,队列长度0
调用第1个任务
线程池线程数:5,队列长度1
调用第2个任务
线程池线程数:5,队列长度1
调用第3个任务
线程池线程数:5,队列长度1
调用第4个任务
线程池线程数:5,队列长度0
调用第5个任务
线程池线程数:5,队列长度1
调用第6个任务
线程池线程数:5,队列长度1
调用第7个任务
线程池线程数:5,队列长度2
调用第8个任务
线程池线程数:5,队列长度3
调用第9个任务
线程池线程数:5,队列长度4
调用第10个任务
线程池线程数:5,队列长度5
调用第11个任务
线程池线程数:5,队列长度6
调用第12个任务
线程池线程数:5,队列长度7
调用第13个任务
线程池线程数:5,队列长度8
调用第14个任务
线程池线程数:5,队列长度9
调用第15个任务
线程池线程数:5,队列长度10
调用第16个任务
线程池线程数:6,队列长度10
调用第17个任务
线程池线程数:7,队列长度10
调用第18个任务
线程池线程数:8,队列长度10
调用第19个任务
线程池线程数:9,队列长度10
调用第20个任务
完成第4个任务
完成第5个任务
完成第17个任务
完成第18个任务
完成第2个任务
完成第1个任务
完成第20个任务
完成第16个任务
完成第3个任务
任务调用完成
完成第19个任务
完成第6个任务
完成第12个任务
完成第9个任务
完成第14个任务
线程池线程数:9,队列长度0
完成第8个任务
完成第10个任务
完成第11个任务
完成第7个任务
完成第13个任务
完成第15个任务
线程池线程数:9,队列长度0
线程池线程数:9,队列长度0
线程池线程数:5,队列长度0
线程池线程数:5,队列长度0
线程池线程数:5,队列长度0
线程池线程数:5,队列长度0

注释掉静态代码块中的pool.prestartAllCoreThreads();再执行线程数会从0开始,线程会在有任务执行的时候再去创建:

线程池线程数:0,队列长度0
调用第1个任务
线程池线程数:1,队列长度0
调用第2个任务
线程池线程数:2,队列长度0
调用第3个任务
线程池线程数:3,队列长度0
调用第4个任务
线程池线程数:4,队列长度0
调用第5个任务
线程池线程数:5,队列长度0
调用第6个任务
线程池线程数:5,队列长度1
调用第7个任务
线程池线程数:5,队列长度2
调用第8个任务
线程池线程数:5,队列长度3
调用第9个任务
线程池线程数:5,队列长度4
调用第10个任务
线程池线程数:5,队列长度5
调用第11个任务
线程池线程数:5,队列长度6
调用第12个任务
线程池线程数:5,队列长度7
调用第13个任务
线程池线程数:5,队列长度8
调用第14个任务
线程池线程数:5,队列长度9
调用第15个任务
线程池线程数:5,队列长度10
调用第16个任务
线程池线程数:6,队列长度10
调用第17个任务
线程池线程数:7,队列长度10
调用第18个任务
线程池线程数:8,队列长度10
调用第19个任务
线程池线程数:9,队列长度10
调用第20个任务
完成第1个任务
完成第2个任务
完成第3个任务
完成第4个任务
完成第5个任务
完成第18个任务
完成第19个任务
完成第20个任务
完成第17个任务
完成第16个任务
任务调用完成
完成第6个任务
完成第7个任务
完成第10个任务
完成第9个任务
完成第8个任务
线程池线程数:9,队列长度0
完成第13个任务
完成第12个任务
完成第14个任务
完成第11个任务
完成第15个任务
线程池线程数:9,队列长度0
线程池线程数:5,队列长度0
线程池线程数:5,队列长度0
线程池线程数:5,队列长度0
线程池线程数:5,队列长度0

线程池任务增长过程分析

标签:system   意义   exec   exe   ise   核心线程   fin   private   throws   

原文:http://blog.51cto.com/wangguangshuo/2349524

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 bubuko.com 版权所有 鲁ICP备09046678号-4
打开技术之扣,分享程序人生!
             

鲁公网安备 37021202000002号