java线程池参数动态化方案


前言:本文章参考美团的线程池动态参数配置。测试有效
解析:jdk提供了一套下线程池参数动态化的api

分为两部分

1.阻塞队列的修改

2.其他参数的修改

第一部分
public class ThreadPoolChangeDemo {

    public static void main(String[] args) throws InterruptedException {
        dynamicThreadPool();
    }

    public static ThreadPoolExecutor buildThreadPool(){
        return new ThreadPoolExecutor(2,
                50,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50),
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread();
                    }
                });
    }

    private static void dynamicThreadPool() throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = buildThreadPool();
        for (int i = 0; i < 15; i++) {
            threadPoolExecutor.submit(()->{
                printPoolSize(threadPoolExecutor,"创建线程池!!!!");
                try {
                    TimeUnit.SECONDS.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        printPoolSize(threadPoolExecutor,"改变之前");
        TimeUnit.SECONDS.sleep(1);
        threadPoolExecutor.setMaximumPoolSize(100);
        threadPoolExecutor.setCorePoolSize(50);
        threadPoolExecutor.prestartAllCoreThreads();
//        Resize linkedBlockingQueue = (LinkedBlockingQueue) threadPoolExecutor.getQueue();
        printPoolSize(threadPoolExecutor,"改变之后");
    }

    private static void printPoolSize(ThreadPoolExecutor pool,String name){
        LinkedBlockingQueue linkedBlockingQueue = (LinkedBlockingQueue) pool.getQueue();
        System.out.println(name);
         System.out.println("最大线程数:"+pool.getMaximumPoolSize());
        System.out.println("核心线程数:"+pool.getCorePoolSize());
        System.out.println("线程池活跃度:"+(pool.getActiveCount()/pool.getMaximumPoolSize()));
        System.out.println("队列大小:"+linkedBlockingQueue.size());
        System.out.println("队列剩余大小:"+linkedBlockingQueue.remainingCapacity());


    }

}

第二部分

思路: LinkedBlockingQueue 粘贴一份出来,修改个自定义的队列名字,然后把 Capacity 参数的 final 修饰符去掉,并提供其对应的 get/set 方法。

java线程池参数动态化方案_第1张图片

然后在程序里面把原来的队列换掉:

java线程池参数动态化方案_第2张图片

运行起来看看效果:

java线程池参数动态化方案_第3张图片

可以看到,队列大小确实从 10 变成了 100,队列使用度从 100% 降到了 9%

这个过程中涉及到的面试题有哪些?

问题一:线程池被创建后里面有线程吗?如果没有的话,你知道有什么方法对线程池进行预热吗?

线程池被创建后如果没有任务过来,里面是不会有线程的。如果需要预热的话可以调用下面的两个方法:

全部启动:

java线程池参数动态化方案_第4张图片

仅启动一个:

java线程池参数动态化方案_第5张图片

问题二:核心线程数会被回收吗?需要什么设置?

核心线程数默认是不会被回收的,如果需要回收核心线程数,需要调用下面的方法:

java线程池参数动态化方案_第6张图片

allowCoreThreadTimeOut 该值默认为 false。

java线程池参数动态化方案_第7张图片

你可能感兴趣的:(技术整理)