2019独角兽企业重金招聘Python工程师标准>>>

微信公众号「后端进阶」,专注后端技术分享:Java、Golang、WEB框架、分布式中间件、服务治理等等。
老司机倾囊相授,带你一路进阶,来不及解释了快上车!

看完我上一篇文章「你都理解创建线程池的参数吗?」之后,当遇到这种问题,你觉得你完全能够唬住面试官了,50k轻松到手。殊不知,要是面试官此刻给你来个反杀:

初始化线程池时可以预先创建线程吗?线程池的核心线程可以被回收吗?为什么?

如果此刻你一脸懵逼,这个要慌,问题很大,50k马上变5k。

有细心的网友早就想到了这个问题:

在ThreadPoolExecutor线程池中,还有一些不常用的设置。我建议如果您在应用场景中没有特殊的要求,就不需要使用这些设置。

初始化线程池时可以预先创建线程吗?

prestartAllCoreThreads

初始化线程池时是可以预先创建线程的,初始化线程池后,再调用prestartAllCoreThreads()方法,即可预先创建corePoolSize数量的核心线程,我们看源码:

public int prestartAllCoreThreads() {int n = 0;while (addWorker(null, true))++n;return n;
}
private boolean addWorker(Runnable firstTask, boolean core) {// ..
}

addWorker方法目的是在线程池中添加任务并执行,如果task为空,线程获取任务执行时调用getTask()方法,该方法从blockingQueue阻塞队列中阻塞获取任务执行,因此线程不会释放,留存在线程池中,如果core=true,说明任务只能利用核心线程来执行。

所以该方法会在线程池总预先创建没有任务执行的线程,数量为corePoolSize。

下面我们测试一下:

从测试结果来看,线程池中已经预先创建了corePoolSize数量的空闲线程。

prestartCoreThread

prestartCoreThread()同样可以预先创建线程,只不过该方法只会与创建1条线程,我们来看源码:

public boolean prestartCoreThread() {return workerCountOf(ctl.get()) < corePoolSize &&addWorker(null, true);
}

从方法源码可知,如果此时工作线程数量小于corePoolSize,那么就调用addWorker创建1条空闲核心线程。

下面我们测试一下:

从测试结果来看,线程池中已经预先创建了1条空闲线程。

线程池的核心线程可以被回收吗?

你可能会想到将corePoolSize的数量设置为0,从而线程池的所有线程都是“临时”的,只有keepAliveTime存活时间,你的思路也许时正确的,但你有没有想过一个很严重的后果,corePoolSize=0时,任务需要填满阻塞队列才会创建线程来执行任务,阻塞队列有设置长度还好,如果队列长度无限大呢,你就等着OOM异常吧,所以用这种设置行为并不是我们所需要的。

有没有什么设置可以回收核心线程呢?

allowCoreThreadTimeOut

ThreadPoolExecutor有一个私有成员变量:

private volatile boolean allowCoreThreadTimeOut;

如果allowCoreThreadTimeOut=true,核心线程在规定时间内会被回收。

上面我也说了,当线程空闲时会从blockingQueue阻塞队列中阻塞获取任务执行,所以我们来看看是保证核心线程不被销毁的,我们直接定位到源码部位:

java.util.concurrent.ThreadPoolExecutor#getTask:

boolean timedOut = false; // Did the last poll() time out?
for (;;) {// Are workers subject to culling?boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;try {Runnable r = timed ?workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :workQueue.take();if (r != null)return r;timedOut = true;} catch (InterruptedException retry) {timedOut = false;}
}

这里的关键值timed,如果allowCoreThreadTimeOut=true或者此时工作线程大于corePoolSize,timed=true,如果timed=true,会调用poll()方法从阻塞队列中获取任务,否则调用take()方法获取任务。

下面我来解释这两个方法:

  1. poll(long timeout, TimeUnit unit):从BlockingQueue取出一个任务,如果不能立即取出,则可以等待timeout参数的时间,如果超过这个时间还不能取出任务,则返回null;
  2. take():从blocking阻塞队列取出一个任务,如果BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的任务被加入为止。

到这里,我们就很好地解释了,当allowCoreThreadTimeOut=true或者此时工作线程大于corePoolSize时,线程调用BlockingQueue的poll方法获取任务,若超过keepAliveTime时间,则返回null,timedOut=true,则getTask会返回null,线程中的runWorker方法会退出while循环,线程接下来会被回收。

下面我们测试一下:

可以看到,核心线程被回收了。

转载于:https://my.oschina.net/objcoding/blog/3036701

关于线程池你不得不知道的一些设置相关推荐

  1. 判断线程是否执行完毕_关于线程池你不能不知道的东西

    前言 平时接触过多线程开发的童鞋应该都或多或少了解过线程池,之前发布的<阿里巴巴 Java 手册>里也有一条: 可见线程池的重要性. 简单来说使用线程池有以下几个目的: 线程是稀缺资源,不 ...

  2. JAVA线程池的简单实现及优先级设置

    我们大家都知道,在处理多线程服务并发时,由于创建线程需要占用很多的系统资源,所以为了避免这些不必要的损耗,通常我们采用线程池来解决这些问题.   线程池的基本原理是,首先创建并保持一定数量的线程,当需 ...

  3. 线程池中各个参数如何合理设置

    欢迎大家关注我的公众号[老周聊架构],Java后端主流技术栈的原理.源码分析.架构以及各种互联网高并发.高性能.高可用的解决方案. 一.前言 在开发过程中,好多场景要用到线程池.每次都是自己根据业务场 ...

  4. Java中,那些关于String和字符串常量池你不得不知道的东西

    老套的笔试题 在一些老套的笔试题中,会要你判断s1==s2为false还是true,s1.equals(s2)为false还是true. String s1 = new String("xy ...

  5. java线程池的工作原理_Java 线程池的介绍以及工作原理

    在什么情况下使用线程池? 1.单个任务处理的时间比较短 2.将需处理的任务的数量大 使用线程池的好处: 1. 降低资源消耗: 通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 2. 提高响应速度 ...

  6. Java线程池实现原理及其在美团业务中的实践

    来自:美团技术团队 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供的线程池ThreadPoolExecuto ...

  7. 关于MySQL线程池,这也许是目前最全面的实用帖!

    作者介绍 张秀云,网名飞鸿无痕,现任职于腾讯,负责腾讯金融数据库的运维和优化工作.2007年开始从事运维方面的工作,经历过网络管理员.Linux运维工程师.DBA.分布式存储运维等多个职位.对Linu ...

  8. JAVA线程池的分析和使用

    1. 引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行.第三:提 ...

  9. java的线程管理器,QuickThread - Java线程池管理器

    QuickThread 特性 任务扩展:支持延迟任务以及异步回调任务; 回调通知:当任务启动时与任务运行完毕后,有分别的生命周期作为通知; 线程切换:可制定是否回调主线程; 使用安全:当线程出现异常. ...

最新文章

  1. Yii2多模型与事务的用法
  2. 学习python需要什么基础-学习python需要什么基础
  3. android提交服务器,Android向WEB服务器提交数据
  4. SAP Intelligent Robotic Process Automation权限控制
  5. .net remoting 技术
  6. RHEL6入门系列之十七,打包与压缩
  7. latax 使用说明
  8. RANDOM模块:PYTHON获取随机数
  9. python万年历代码_利用python实现万年历
  10. GD32系列总结 - 前言
  11. 怎么用计算机自己做动画片,怎样用电脑制作动画,电脑动画制作怎么做
  12. css调logo大小,css实现宽高不同的logo水平排列
  13. 新一代数据仓库:Snowflake 弹性数仓介绍
  14. 红警地图编辑器的使用方法
  15. 微信红包数字变化动态图片_微信红包数字动图下载_微信动态图片红包图下载_游戏吧...
  16. 免安装版jdk的配置及使用(附绿色版jdk1.7及jdk1.8)
  17. 腾讯云服务器php设置,Windows 腾讯云服务器的 PHP 配置
  18. 邮件中html内嵌图片,邮件内嵌html
  19. VOSviewer进行中文和英文文献分析
  20. 抖音播放量突然被限流降权是什么原因

热门文章

  1. 重复提交版本之后该采取的测试策略
  2. cdr放大后内容消失了_放大镜+定时器+画笔,582KB软件就能做到,上网课的你一定能用上...
  3. webbrowser 百度列表点击_百度信息流推广后台完整的实操流程!
  4. termux python 打开摄像头_【图片】将termux打造成合格的python环境(假装是教程贴)_termux吧_百度贴吧...
  5. nemanja AJAX,通过AJAX发送空值 - ASP.NET MVC
  6. python excel增加一列_(用Python修改excel中一列数据)python新增一列
  7. log4j写入mysql数据库_log4j日志写入数据库
  8. 基于场效应管2N3819制作非接触电压检测 - 购买到假货了
  9. 如何打赢一场唯快不破的比赛,看看他们的绝招
  10. 2021年春季学期-信号与系统-第十二次作业参考答案-第七小题