如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。(3)

简介: 如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。(3)

动态设置的注意点有哪些?


调整的时候可能会出现核心线程数调整之后无效的情况,比如下面这种:


改变之前的核心线程数是 2,最大线程数为 5,我们动态修改核心线程数为 10。

但是从日志还是可以看出,修改之后核心线程数确实变成了 10,但活跃线程数还是为 5。


而且我调用了 prestartCoreThread 方法,该方法见名知意,你也知道是启动所有的核心线程数,所有不存在线程没有创建的问题。


这是为什么呢?


源码之下无秘密,我带你去看一眼:


java.util.concurrent.ThreadPoolExecutor#getTask


在这个方法中我们可以看到,如果工作线程数大于最大线程数,则对工作线程数量进行减一操作,然后返回 null。


所以,这个地方的实际流程应该是: 创建新的工作线程 worker,然后工作线程数进行加一操作。 运行创建的工作线程 worker,开始获取任务 task。 工作线程数量大于最大线程数,对工作线程数进行减一操作。 返回 null,即没有获取到 task。 清理该任务,流程结束。


这样一加一减,所以真正在执行任务的工作线程数的数量一直没有发生变化,也就是最大线程数。


怎么解决这个问题呢?


答案已经呼之欲出啦。


设置核心线程数的时候,同时设置最大线程数即可。其实可以把二者设置为相同的值:


这样,活动线程数就能正常提高了。


有的小伙伴就会问了:如果调整之后把活动线程数设置的值太大了,岂不是业务低峰期我们还需要人工把值调的小一点?


不存在的,还记得前面介绍 corePoolSize 参数的含义时的注解吗:


当 allowCoreThreadTimeOut 参数设置为 true 的时候,核心线程在空闲了

keepAliveTime 的时间后也会被回收的,相当于线程池自动给你动态修改了。


如何动态指定队列长度?


前面介绍了最大线程数和核心线程数的动态设置,但是你发现了吗,并没有设置队列长度的 set 方法啊?


有的小机灵鬼说先获取 Queue 对象出来再看一下呢?


还是没有,这可咋整呢?


首先我们看一下为什么没有提供队列长度的 set 方法呢:


因为队列的 capacity 是被 final 修饰了呀。


但是美团的那篇文章明明说了,他们也支持队列的动态调整呀:


可是没有详细说明,但是别着急,接着看后面的内容可以发现他们有一个名字为 ResizableCapacityLinkedBlockIngQueue 的队列:


很明显,这是一个自定义队列了。


我们也可以按照这个思路自定义一个队列,让其可以对 Capacity 参数进行修改即可。

操作起来也非常方便,把 LinkedBlockingQueue 粘贴一份出来,修改个名字,然后把 Capacity 参数的 final 修饰符去掉,并提供其对应的 get/set 方法。


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


运行起来看看效果:


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

我后来去看了美团的那篇文章下面的评论,有个评论是这样的:


果然不出我所料。


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


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


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

全部启动:


仅启动一个:


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


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


allowCoreThreadTimeOut 该值默认为 false。


最后说一句(求关注)


点个赞吧,周更很累的,不要白嫖我,需要一点正反馈。


才疏学浅,难免会有纰漏,如果你发现了错误的地方,由于本号没有留言功能,还请你加我微信给我指出来,我对其加以修改。(我每篇技术文章都有这句话,我是认真的说的。)


感谢您的阅读,我坚持原创,十分欢迎并感谢您的关注。


我是why技术,一个不是大佬,但是喜欢分享,又暖又有料的四川好男人。


欢迎关注公众号【why技术】,坚持输出原创。分享技术、品味生活,愿你我共同进步。

目录
相关文章
|
2天前
|
Java 数据库连接 调度
面试题:用过线程池吗?如何自定义线程池?线程池的参数?
字节跳动面试题:用过线程池吗?如何自定义线程池?线程池的参数?
31 0
|
18小时前
|
机器学习/深度学习 PyTorch 算法框架/工具
神经网络基本概念以及Pytorch实现,多线程编程面试题
神经网络基本概念以及Pytorch实现,多线程编程面试题
|
22小时前
|
Java
阅读《代码整洁之道》总结(1),java多线程面试
阅读《代码整洁之道》总结(1),java多线程面试
|
22小时前
|
缓存 安全 Java
7张图带你轻松理解Java 线程安全,java缓存机制面试
7张图带你轻松理解Java 线程安全,java缓存机制面试
|
1天前
|
消息中间件 前端开发 Java
美团面试:如何实现线程任务编排?
线程任务编排指的是对多个线程任务按照一定的逻辑顺序或条件进行组织和安排,以实现协同工作、顺序执行或并行执行的一种机制。 ## 1.线程任务编排 VS 线程通讯 有同学可能会想:那线程的任务编排是不是问的就是线程间通讯啊? 线程间通讯我知道了,它的实现方式总共有以下几种方式: 1. Object 类下的 wait()、notify() 和 notifyAll() 方法; 2. Condition 类下的 await()、signal() 和 signalAll() 方法; 3. LockSupport 类下的 park() 和 unpark() 方法。 但是,**线程通讯和线程的任务编排是
|
2天前
|
Java
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
24 0
|
2天前
|
安全 Java 程序员
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
12 0
|
2天前
|
消息中间件 监控 前端开发
面试官:核心线程数为0时,线程池如何执行?
线程池是 Java 中用于提升程序执行效率的主要手段,也是并发编程中的核心实现技术,并且它也被广泛的应用在日常项目的开发之中。那问题来了,如果把线程池中的核心线程数设置为 0 时,线程池是如何执行的? 要回答这个问题,我们首先要了解在正常情况下,线程池的执行流程,也就是说当有一个任务来了之后,线程池是如何运行的? ## 1.线程池的执行流程 正常情况下(核心线程数不为 0 的情况下)线程池的执行流程如下: 1. **判断核心线程数**:先判断当前工作线程数是否大于核心线程数,如果结果为 false,则新建线程并执行任务。 2. **判断任务队列**:如果大于核心线程数,则判断任务队列是否
22 1
面试官:核心线程数为0时,线程池如何执行?
|
2天前
|
安全 Java
美团一面,面试官让介绍AQS原理并手写一个同步器,直接凉了
美团一面,面试官让介绍AQS原理并手写一个同步器,直接凉了
30 6
|
2天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题