欢迎关注我的公众号:石杉的架构笔记(ID:shishan100)程序员
周一至周五早8点半!精品技术文章准时送上!面试
(1)背景引入算法
(2)线程池是如何构造的?缓存
(3)线程池的运行原理性能优化
(4)无界队列引起的内存飙升架构
今天跟你们聊一个互联网大厂的Java面试题:使用无界队列的线程池会致使内存飙升吗?并发
由于在面互联网大厂的时候,必定会问并发,问并发的时候必定会问到线程池,问到线程池必定会问构造线程池的一些参数的含义。分布式
而后,有一些面试官会就线程池的具体场景,问一些可能会遇到的问题。微服务
因此,在这里就可能有上述那样一个面试中的问题,算是Java面试里相对来讲高阶一点的。高并发
我相信你们必定起码知道线程池是个什么东西的。简单来讲,就是维护一个池子,池子里面放了不少的线程。
而后来一个任务,某个线程就获取这个任务来执行,任务执行完以后线程是不会释放掉的,而是停留在线程池里继续等待下一个任务。
这样的一个好处是你不必本身手动频繁的建立和销毁线程,毕竟线程是较重的资源,频繁的建立和销毁对系统性能是没好处的。
咱们看看下面的图,回顾一下线程池的含义。
那么平时在Java里写代码的时候,你们记得不记得线程池是如何构造出来的呢?
是否是相似下面那样的代码,好比说咱们构造一个线程数量固定的一个线程池:
其实很简单,翻开JDK源码就能够看到里面的代码以下:
corePoolSize maximumPoolSize keepAliveTime workQueue
假如说咱们构造线程池传入的线程数量是10,那么在这里,corePoolSize和maximumSize都是10,keepAliveTime默认就是0,workQueue是一个无界的LinkedBlockingQueue。
接下来,咱们具体来看看构造一个线程池传入一些参数以后,具体这个线程池的运行原理是什么。
简单来讲,刚开始的时候其实线程池里是空的,就是一个线程都没有的,以下图所示。
接着若是你使用线程池提交一个任务进去,但愿由线程池里的一个线程来执行,以下代码所示,就是提交一个任务:
如今线程池里的线程数量是0,而后corePoolSize是10,那么确定没达到了,因此直接会在线程池里建立一个线程出来而后执行这个任务,以下图。
接着假如说,这个线程处理完一个任务了,那么此时线程是不会被销毁的,他会一直等待下一个提交过来的任务。
那么,究竟是怎么等待的呢?
很简单,线程池会搭配一个workQueue,好比这里搭配的就是一个无界的LinkedBlockingQueue,几乎能够无限量放入任务。
而后那个线程处理完一个任务以后,就会用阻塞的方式尝试从任务队列里获取任务,若是队列是空的,他就会阻塞卡在那儿不动,直到有人放一个任务到队列里,他才会获取到一个任务而后继续执行,循环往复,以下图。
接着再次提交任务,线程池一判断发现,诶?好像线程数量才只有1个,彻底比corePoolSize(10个)要小,那么继续直接在池子里建立一个线程,而后处理这个任务,处理完了继续尝试从workQueue里阻塞式获取任务。
一直重复上面的操做,直到线程池里有10个线程了,达到了corePoolSize指定的数量,以下图。
这个时候你若是再提交任务,他一会儿发现,诶?不对啊,线程池里已经有10个线程了,跟corePoolSize指定的线程数量同样了。
那么如今,我就不须要建立任何一个额外的线程了,如今你只要提交任务,所有直接入队到workQueue里就好。
此时线程池里的线程都阻塞式在workQueue上等待获取任务,有一个任务进来就会唤醒一个线程来处理这个任务,处理完了任务再次阻塞在workQueue上尝试获取下一个任务,以下图所示这个意思。
这里咱们看到他用的是一个无界的LinkedBlockingQueue,可是假如说他用的是一个有界的队列呢?
好比说限定好了队列最多只能放10个任务,那么假如说,线程池里的线程来不及处理任务了,而后队列一会儿放满了10个任务。
此时就会出现任务入队的失败,由于队列满了,没法入队。
而后就会尝试再次在线程池里建立线程,这个时候就会一直建立线程直到线程池里的线程数量达到maximumPoolSize指定的数量为止。
虽然这里fixed线程池默认corePoolSize和maximumPoolSize的数量都是一致的,可是能够假设此时maximumPoolSize的数量是20呢?
那么就会继续建立线程,直到线程数量达到20个,而后用额外建立的10个线程在队列满的状况下,继续处理任务。
整个过程,以下图所示:
接着万一队列满了,而后线程池的线程数量达到了maximumPoolSize指定的数量了,你额外建立线程都没法建立了,此时会如何呢?
答案是:会reject掉,不让你继续提交任务了,此时默认的就是抛出一个异常。
那么,在上图中额外建立出来的,超出corePoolSize的那些线程呢?
他们一旦建立出来以后,会发现线程池数量已经超过corePoolSize了,此时他们会尝试等待workQueue里的任务。
一旦超过keepAliveTime指定的时间,还获取不到任务,好比keepAliveTime是60秒,那么假如超过60秒获取不到任务,他就会自动释放掉了,这个线程就销毁了。
整个过程,以下图所示。
明白了线程池的运行原理了,这个面试题就好解答了。
咱们以最经常使用的fixed线程池举例,他的线程池数量是固定的,由于他用的是近乎于无界的LinkedBlockingQueue,几乎能够无限制的放入任务到队列里。
因此只要线程池里的线程数量达到了corePoolSize指定的数量以后,接下来就维持这个固定数量的线程了。
而后,全部任务都会入队到workQueue里去,线程从workQueue获取任务来处理。
这个队列几乎永远不会满,固然这是几乎,由于LinkedBlockingQueue默认的最大任务数量是Integer.MAX_VALUE,很是大,近乎于能够理解为无限吧。
只要队列不满,就跟maximumPoolSize、keepAliveTime这些不要紧了,由于不会建立超过corePoolSize数量的线程的。
一样,给你们来一张图,咱们来看看:
那么此时万一每一个线程获取到一个任务以后,他处理的时间特别特别的长,长到了使人发指的地步。好比处理一个任务要几个小时,此时会如何?
固然会出现workQueue里不断的积压愈来愈多得任务,不停的增长。
这个过程当中会致使机器的内存使用不停的飙升,最后也许极端状况下就致使JVM OOM了,系统就挂掉了。
因此这就是这个面试题背后你要知道的线程池的运行原理,以及可能遇到的一些问题,你们要作到内心有数。
扫描下方二维码,备注:“资料”,获取更多“秘制” 精品学习资料
若有收获,请帮忙转发,您的鼓励是做者最大的动力,谢谢!
一大波微服务、分布式、高并发、高可用的原创系列文章正在路上
欢迎扫描下方二维码,持续关注:
石杉的架构笔记(id:shishan100)
十余年BAT架构经验倾囊相授
推荐阅读:
二、【双11狂欢的背后】微服务注册中心如何承载大型系统的千万级访问?
三、【性能优化之道】每秒上万并发下的Spring Cloud参数优化实战
六、大规模集群下Hadoop NameNode如何承载每秒上千次的高并发访问
七、【性能优化的秘密】Hadoop如何将TB级大文件的上传性能优化上百倍
九、【坑爹呀!】最终一致性分布式事务如何保障实际生产中99.99%高可用?
十一、【眼前一亮!】看Hadoop底层算法如何优雅的将大规模集群性能提高10倍以上?
1六、亿级流量系统架构之如何设计全链路99.99%高可用架构
1八、大白话聊聊Java并发面试问题之volatile究竟是什么?
1九、大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?
20、大白话聊聊Java并发面试问题之谈谈你对AQS的理解?
2一、大白话聊聊Java并发面试问题之公平锁与非公平锁是啥?
2二、大白话聊聊Java并发面试问题之微服务注册中心的读写锁优化
2三、互联网公司的面试官是如何360°无死角考察候选人的?(上篇)
2四、互联网公司面试官是如何360°无死角考察候选人的?(下篇)
2五、Java进阶面试系列之一:哥们,大家的系统架构中为何要引入消息中间件?
2六、【Java进阶面试系列之二】:哥们,那你说说系统架构引入消息中间件有什么缺点?
2七、【行走的Offer收割机】记一位朋友斩获BAT技术专家Offer的面试经历
2八、【Java进阶面试系列之三】哥们,消息中间件在大家项目里是如何落地的?
2九、【Java进阶面试系列之四】扎心!线上服务宕机时,如何保证数据100%不丢失?
30、一次JVM FullGC的背后,竟隐藏着惊心动魄的线上生产事故!
3一、【高并发优化实践】10倍请求压力来袭,你的系统会被击垮吗?
3二、【Java进阶面试系列之五】消息中间件集群崩溃,如何保证百万生产数据不丢失?
3三、亿级流量系统架构之如何在上万并发场景下设计可扩展架构(上)?
3四、亿级流量系统架构之如何在上万并发场景下设计可扩展架构(中)?
3五、亿级流量系统架构之如何在上万并发场景下设计可扩展架构(下)?
3七、亿级流量系统架构之如何保证百亿流量下的数据一致性(上)
3八、亿级流量系统架构之如何保证百亿流量下的数据一致性(中)?
3九、亿级流量系统架构之如何保证百亿流量下的数据一致性(下)?
40、互联网面试必杀:如何保证消息中间件全链路数据100%不丢失(1)
4一、互联网面试必杀:如何保证消息中间件全链路数据100%不丢失(2)
4三、高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?
4五、从团队自研的百万并发中间件系统的内核设计看Java并发性能优化
4六、【非广告,纯干货】英语差的程序员如何才能无障碍阅读官方文档?
4七、若是20万用户同时访问一个热点缓存,如何优化你的缓存架构?
4八、【非广告,纯干货】中小公司的Java工程师应该如何逆袭冲进BAT?
做者:石杉的架构笔记 连接:juejin.im/post/5c263a… 来源:掘金 著做权归做者全部,转载请联系做者得到受权!