当前位置: 首页 > news >正文

ThreadPoolExecutor运行机制

最近发现几起对ThreadPoolExecutor的误用,其中包括自己,发现都是因为没有仔细看注释和内部运转机制,想当然的揣测参数导致,先看一下新建一个ThreadPoolExecutor的构建参数:

[java]  view plain  copy
  1. public ThreadPoolExecutor(int corePoolSize,  
  2.                           int maximumPoolSize,  
  3.                           long keepAliveTime,  
  4.                           TimeUnit unit,  
  5.                           BlockingQueue<Runnable> workQueue,  
  6.                           ThreadFactory threadFactory,  
  7.                           RejectedExecutionHandler handler)  

看这个参数很容易让人以为是线程池里保持corePoolSize个线程,如果不够用,就加线程入池直至maximumPoolSize大小,如果还不够就往workQueue里加,如果workQueue也不够就用RejectedExecutionHandler来做拒绝处理。

但实际情况不是这样,具体流程如下:

1)当池子大小小于corePoolSize就新建线程,并处理请求

2)当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去从workQueue中取任务并处理

3)当workQueue放不下新入的任务时,新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理

4)另外,当池子的线程数大于corePoolSize的时候,多余的线程会等待keepAliveTime长的时间,如果无请求可处理就自行销毁

内部结构如下所示:

从中可以发现ThreadPoolExecutor就是依靠BlockingQueue的阻塞机制来维持线程池,当池子里的线程无事可干的时候就通过workQueue.take()阻塞住。

其实可以通过Executes来学学几种特殊的ThreadPoolExecutor是如何构建的。

[java]  view plain  copy
  1. public static ExecutorService newFixedThreadPool(int nThreads) {  
  2.     return new ThreadPoolExecutor(nThreads, nThreads,  
  3.                                   0L, TimeUnit.MILLISECONDS,  
  4.                                   new LinkedBlockingQueue<Runnable>());  
  5. }  

newFixedThreadPool就是一个固定大小的ThreadPool

[java]  view plain  copy
  1. public static ExecutorService newCachedThreadPool() {  
  2.     return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  
  3.                                   60L, TimeUnit.SECONDS,  
  4.                                   new SynchronousQueue<Runnable>());  
  5. }  

newCachedThreadPool比较适合没有固定大小并且比较快速就能完成的小任务,没必要维持一个Pool,这比直接new Thread来处理的好处是能在60秒内重用已创建的线程。

其他类型的ThreadPool看看构建参数再结合上面所说的特性就大致知道它的特性

相关文章:

  • 循环创建按钮
  • python3-itertools模块和迭代器函数
  • Java字节码浅析(三)
  • swift学习笔记
  • Java静态代码分析工具——FindBugs插件的安装与使用
  • 好看的网站
  • 面试题解答
  • 大话队列
  • python 学习笔记2(list/directory/文件对象/模块/参数传递)
  • 干货--JMS(java消息服务)整合Spring项目案例
  • Java基础学习总结(38)——Lombok的使用和原理
  • Educational Codeforces Round 11
  • 程序中的得与失
  • nodejs中下载文件回调问题
  • 你所不知的SEO高级策略技巧
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【剑指offer】让抽象问题具体化
  • 4个实用的微服务测试策略
  •  D - 粉碎叛乱F - 其他起义
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • IDEA常用插件整理
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • springboot_database项目介绍
  • Swoft 源码剖析 - 代码自动更新机制
  • Terraform入门 - 3. 变更基础设施
  • webpack入门学习手记(二)
  • 阿里云前端周刊 - 第 26 期
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 那些年我们用过的显示性能指标
  • 区块链分支循环
  • 怎样选择前端框架
  • ​iOS实时查看App运行日志
  • ​香农与信息论三大定律
  • #Linux(make工具和makefile文件以及makefile语法)
  • #数学建模# 线性规划问题的Matlab求解
  • #图像处理
  • (52)只出现一次的数字III
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (阿里云万网)-域名注册购买实名流程
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (分享)自己整理的一些简单awk实用语句
  • (生成器)yield与(迭代器)generator
  • (一)u-boot-nand.bin的下载
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • **CI中自动类加载的用法总结
  • *1 计算机基础和操作系统基础及几大协议
  • ..回顾17,展望18
  • .cfg\.dat\.mak(持续补充)
  • .NET 4.0中的泛型协变和反变
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net反编译的九款神器
  • .NET应用架构设计:原则、模式与实践 目录预览