电话面试,面试内容中规中矩,循序渐进,对于项目业务上问的不多,总体还不错,面试没有标准答案,千人千面,记录以备后用
巴拉巴拉小魔仙,提前打好一些草稿,各家都没什么区别
这都是最基本的东西了,但是如果可以把细节说清楚,也能是个亮点,但是有些细节点,还是人家自己的注释说的清楚,只看博客文章很多一笔带过了,看不懂的直接百度翻译吧。
a.corePoolSize(核心线程数 ):要保留在池中的线程数,甚至如果它们是空闲的,除非设置了参数allowCoreThreadTimeOut,默认为不设置,也就是说线程池一般情况最小线程数即为核心线程数
/**
* If false (default), core threads stay alive even when idle.
* If true, core threads use keepAliveTime to time out waiting
* for work.
*/
private volatile boolean allowCoreThreadTimeOut;
b.maximumPoolSize(最大线程数),纸面意思无特殊地方
c.keepAliveTime(超时时间),空闲等待的最大时间
d.unit(时间单位)
e.workQueue(线程队列),队列有多种,主要分两类,一类有界队列,一类无解队列
f.threadFactory(线程工厂),工厂有多种
g.handler(拒绝策略),有多种
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
举例:核心线程数:5,最大线程数10,存活时间:5分钟,队列大小:20
第一个线程放入时,线程池状态:核心线程数:0,线程池存活线程数:0,线程队列:0
直接创建线程提交任务执行。
线程池状态:核心线程数:5,线程池存活线程数:6,线程队列:~
这里有个坑,情况分两种:一种是
a.如果队列未满,放入队列执行
b.如果队列已满,再看是否达到最大线程数,如果未达到,创建线程执行,并不是执行拒绝策略。我原来也是任务直接异常抛出,但其实不是
这里没有找到官方的解释,但是我在一片文档的评论里找到一个很有说服力的观点,因为不是实名制的所以就没有具体归属了
一个“mo”的同学,原文是这样:举个例子,5个程序员开发5个需求,能有条不紊地开发,加入又来了3个需求,排下期,5个开发依旧能搞定,但这个时候忽然又来了10个需求,5个程序员超负荷运转也完成不了,这个时候怎么办呢,该招人了吧。但是招人也是需要到一定条件才招的,不是来一个需求就需要招一个人,到时候需求开发完了,新招的人裁掉是要付很大代价的。猜想线程池的原理也大概如此,核心池满了后新来一任务就新开一线程处理,直到撑到最大线程数,到时候一空闲下来又得销毁,线程池经历这频繁地创建与销毁,性能也会有所损失,而有效地先利用等待队列,则能发挥出线程池原本的能力”
依据这个故事,其实也就可以很好理解一下题目3的顺序了,为什么是先创建线程,而不是先放入队列了。
主要考察点线程池里的线程回收机制
主要考察点也就是上面核心参数的讲解条件了,核心线程是否会被回收,与那些条件有关。
8.多线程sync 为什么需要与await,notify一起使用
9.sync是重入锁么?是如何重入的? sync是如何保证线程安全的
10.lock是重入锁么?
11.aqs是如何保证线程安全的?
12.redis的缓存,如果数据库中没有查询到相关的值?如何操作?
13.redis缓存失效问题
14.商品信息放入缓存之后,运营修改部分菜单 如何进行缓存更新?
15.redis的集群和哨兵有什么区别?如何选择
16.IOC和DI的区别
17.代理类再spring中有哪些应用
以上问题可以参考文献
线程池相关,感觉讲的特别详细的不多:https://mp.weixin.qq.com/s/HczCB_vklzChfrdrnGjHSw
AQS相关:https://blog.csdn.net/weixin_39506180/article/details/105156150