前言:本文章参考美团的线程池动态参数配置。测试有效
解析: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 方法。
然后在程序里面把原来的队列换掉:
运行起来看看效果:
可以看到,队列大小确实从 10 变成了 100,队列使用度从 100% 降到了 9%
这个过程中涉及到的面试题有哪些?
问题一:线程池被创建后里面有线程吗?如果没有的话,你知道有什么方法对线程池进行预热吗?
线程池被创建后如果没有任务过来,里面是不会有线程的。如果需要预热的话可以调用下面的两个方法:
全部启动:
仅启动一个:
问题二:核心线程数会被回收吗?需要什么设置?
核心线程数默认是不会被回收的,如果需要回收核心线程数,需要调用下面的方法:
allowCoreThreadTimeOut 该值默认为 false。