本文转载自微信公众号「安琪拉的博客」,作者安琪拉的博客 。转载本文请联系安琪拉的博客公众号。
我们提供的服务有:做网站、成都做网站、微信公众号开发、网站优化、网站认证、荔波ssl等。为1000+企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的荔波网站制作公司
这篇是并发编程系列文章第五篇了,说到并发编程,怎么少的了线程池,在阿里线程池使用场景非常多,用好线程池这个利器也算是日常开发必须掌握的了,下面讲讲2019年的那一夜,就线程池和某位面试官鏖战了半个小时。
面试官 : 看你简历上写了对系统性能做了优化,能简单给我介绍一下吗?都有哪些优化,你是怎么衡量优化效果的?
我 : 巴拉巴拉。例如我们系统之前要查询用户的个人身份信息、联系人信息、订单状态信息、积分信息,之前系统是单线程串行处理的,我用线程池对四个任务并行处理,然后对处理结果合并。
面试官 : 你刚才说用到线程池,能跟我讲讲为什么用线程池吗?我创建四个线程处理可不可以?
我 : 可以,当然可以。
我 : 但是用线程池更合适。阿里巴巴开发规约中有一条:
3.【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
《阿里巴巴研发手册》
我 : 就像你去餐厅吃饭,服务员总是提前洗好盘子,不会等你来打饭的时候才洗盘子,盘子就像是线程池里的线程,你打饭就是要处理的任务。
面试官 : 那你知道线程池的相关类关系吗?
我: 这算什么问题?不应该是问我核心线程数怎么设置吗?好吧。请看下图:
- public interface Executor {
- void execute(Runnable command);
- }
面试官 : 那你日常开发中是怎么创建线程池的?
我: 我用ThreadPoolExecutor 自定义创建线程池。
面试官 : 那你知道线程池都有哪些核心参数吗?
我: 线程池主要的核心参数有7个,我们看 ThreadPoolExecutor 构造函数就知道了
面试官 : 老实说,你是不是来之前背过了,不然怎么可能都记住了。
我: [掀桌子],不面了,还找什么工作,要什么自行车。
我不过是来之前把“安琪拉的博客”公众号上的文章都看了个遍。
面试官 : 其实刚才那也是问题,考察面试者是否皮实,我们继续。
面试官 : 刚才说了这些核心参数,你能不能跟我讲讲线程池的基本工作原理。
我: 可以的,这里我给你画个流程,如下所示:
面试官 : 那按照上面的流程写段伪代码。
我: 还能不能好好面了,让手撕线程池。
那好吧,你对着的流程图看,代码如下:
面试官 : 不错,那你平常怎么管理线程池的呢?
我: 我会搞了个线程池管理器,比如 ThreadPoolManager,有个私有变量的Map,按照线程池的作用给他取个名字,比如起名为: preparePlateThreadPool (准备餐盘线程池),把线程池名称定义成常量,和创建好的线程池放到管理器的Map里。
面试官 : 除了你自己用 ThreadPoolExecutor 创建线程池,还有别的方式吗?
我: java.util.concurrent 包里提供的 Executors 也可以用来创建线程池。
面试官 : Executors 定义了哪几种 ?
我:
面试官 : 你上面讲日常开发自己 用 ThreadPoolExecutor 创建线程池,为什么不用Executors 提供的。
我: 第一是 Executors 提供的线程池使用场景很有限,一般场景很难用到,第二他们也都是通过 ThreadPoolExecutor 创建的线程池,我直接用 ThreadPoolExecutor 创建线程池,可以理解原理,灵活度更高。
参考阿里开发手册规约:
4.【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors返回的线程池对象的弊端如下:
1)FixedThreadPool和SingleThreadPool:
2)CachedThreadPool:
《阿里巴巴研发手册》
面试官 : 前面你代码里有任务入队的操作,你一般自定义线程池,用的什么队列?
我: 这个要看实际应用的。
面试官 : 那你怎么保证任务队列的可用性呢?
我: 分几个方面:
面试官 : 那你怎么合理拆分线程池,核心任务数和任务队列大小的呢?
我: 这个是个老生常谈的问题。
【推荐】 了解每个服务大致的平均耗时,可以通过独立线程池配置,将较慢的服务与主线程池隔离开,不致于各服务线程同归于尽。
《阿里巴巴研发手册》
这里还有个公式借鉴:最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
也有开源的辅助测算线程池的合理线程数。
面试官 : 那拒绝策略呢?了解吗
我: 拒绝策略就是当任务太多,超过maximumPoolSize了,只能拒绝。
面试官 : 详细讲讲
我: 拒绝的时候可以指定拒绝策略,也可以自己实现,JDK默认提供了四种拒绝策略.
默认拒绝策略, 直接抛RejectedExecutionException
任务直接丢弃,不抛出异常
由调用者来执行被拒绝的任务,比如主线程调用线程池的submit提交任务,但是任务被拒绝,则主线程直接执行。
但是线程池如果已经被关闭了,任务就被丢弃了。
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- //线程池没关闭
- if (!e.isShutdown()) {
- //直接run,没有让线程池来执行
- r.run();
- }
- }
丢弃队列里等的最久的任务,然后尝试执行被拒绝的任务。
但是线程池如果已经被关闭了,任务就被丢弃了
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- if (!e.isShutdown()) {
- //丢弃队列头部任务
- e.getQueue().poll();
- //线程池尝试执行任务
- e.execute(r);
- }
- }
- 面试官 : 那这几种拒
面试官 : 那这几种拒绝策略,你选哪一种?
我: 我选拒绝回答
面试官 : 我选你回去等通知。
到年底了,蚂蚁现在有些岗位放出来,有挑战的业务场景,6位数QPS,流程加快,拿完年终,过完年直接来上班,这个点竞争压力小。
不管想不想来都可以来找我聊聊,我的微信: guofu-angela。
分享标题:面试被问线程池,真香
新闻来源:http://www.mswzjz.cn/qtweb/news44/234444.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能