线程池面试必考
你对 Java 线程池了解吗?你有用过线程池吗?那先说下线程池核心参数吧。。。对不起,我回去再看看吧。
为了一丝体面,我们今天来整理几个面试中常考线程池面试问题吧!
为什么要用线程池?
线程复用。线程的重复使用是线程池设计的重点,如果需要开启 1000 个线程执行程序,系统会创建 1000 个线程,如果用线程池来执行 1000 个任务,并不需要开启 1000 个线程,只需要设置 corePoolSize 核心线程大小数量,最大线程数量,队列大小即可重复利用线程置换任务,而且 1000 个线程切换效率并不低,也就是说线程越多效率不一定高。所以在多线程环境实际开发中我们推荐用多线程。
更好的管理线程。ThreadPoolExecutor 可以控制线程数量,根据实际应用场景设置队列数量和饱和策略。
你说下线程池核心参数?
corePoolSize : 核心线程大小。线程池一直运行,核心线程就不会停止。
maximumPoolSize :线程池最大线程数量。非核心线程数量=maximumPoolSize-corePoolSize
keepAliveTime :非核心线程的心跳时间。如果非核心线程在 keepAliveTime 内没有运行任务,非核心线程会消亡。
workQueue :阻塞队列。ArrayBlockingQueue,LinkedBlockingQueue 等,用来存放线程任务。
defaultHandler :饱和策略。
ThreadFactory :线程工厂。新建线程工厂。
execute 任务添加流程?
线程池执行 execute/submit 方法向线程池添加任务,当任务小于核心线程数 corePoolSize,线程池中可以创建新的线程。
当任务大于核心线程数 corePoolSize,就向阻塞队列添加任务。
如果阻塞队列已满,需要通过比较参数 maximumPoolSize,在线程池创建新的线程,当线程数量大于 maximumPoolSize,说明当前设置线程池中线程已经处理不了了,就会执行饱和策略。
饱和策略知道吗?
上图我们说过,当线程数量大于 maximumPoolSize,就会执行饱和策略。ThreadPoolExecutor 类中一共有 4 种饱和策略。通过实现 RejectedExecutionHandler 接口。
AbortPolicy : 线程任务丢弃报错。默认饱和策略。
DiscardPolicy : 线程任务直接丢弃不报错。
DiscardOldestPolicy : 将 workQueue 队首任务丢弃,将最新线程任务重新加入队列执行。
CallerRunsPolicy :线程池之外的线程直接调用 run 方法执行。
下面我们在代码中看下饱和策略使用方式。
如上代码:核心线程数量是 3,最大线程数量是 5,阻塞队列是 20,共提交 50 个线程,这里饱和策略用的是 AbortPolicy,分析执行线程池过程,线程池中首先开启 3 个核心线程 Worker,发现 3 个线程处理不了 50 个线程任务,于是线程池就向阻塞队列添加任务,发现还是阻塞队列也容纳不下 50 个任务,于是又增加至 2 个线程同时运行线程任务,一共是 5 个线程同时运行任务,此时线程池中共有 25 个任务会被执行,还有 25 个任务会被丢弃,因为我们用的是 AbortPolicy 饱和策略,会报错,截部分图如下划红线所示。一共执行了 25 个任务。其他几种策略大家可以参照执行。
你平时线程池怎么用的?
Excutors.newSingleThreadExecutor :1 个 corePoolSize,LinkedBlockingQueue 队列无限大,当创建无数个线程,队列无限长,可能出现 OOM 内存溢出。单一线程。
Executors.newCachedThreadPool :0 个 corePoolSize,Interger.MAX_VALUE 个最大线程数,当创建无数个线程,可能出现 OOM 内存溢出。适用小而多线程。
Executors.newFixedThreadPool :n 个 corePoolSize,n 个最大线程个数,LinkedBlockingQueue 阻塞队列,当创建无数个线程,队列无限长,可能出现 OOM 内存溢出。适用固定线程。
Executors.newScheduledThreadPool :n 个 corePoolSize,Interger.MAX_VALUE 个最大线程数,当创建无数个线程,可能出现 OOM 内存溢出。
源码中线程池是怎么复用线程的?
源码中 ThreadPoolExecutor 中有个内置对象 Worker,每个 worker 都是一个线程,worker 线程数量和参数有关,每个 worker 会 while 死循环从阻塞队列中取数据,通过置换 worker 中 Runnable 对象,运行其 run 方法起到线程置换的效果,这样做的好处是避免多线程频繁线程切换,提高程序运行性能。
总结
今天我们介绍了线程池中面试中几个重要的面试点,整理出来希望能对你有帮助,写的比不全,同时还有许多需要修正的地方,希望亲们加以指正和点评,喜欢的请点赞加关注哦。点关注,不迷路,我是叫练【公众号】,微信号【jiaolian123abc】边叫边练。
版权声明: 本文为 InfoQ 作者【叫练】的原创文章。
原文链接:【http://xie.infoq.cn/article/181ca6e0121d8d79941e940f3】。文章转载请联系作者。
评论