在Executors类中,jdk提供了四个线程池可以使用,分别是
newCachedThreadPool:
corePoolSize是0,允许创建的最大线程数量是Integer.MAX_VALUE
newScheduledThreadPool:
允许创建的最大线程数量是Integer.MAX_VALUE
newFixedThreadPool:
任务队列允许的最大长度是Integer.MAX_VALUE
newSingleThreadExecutor:
任务队列允许的最大长度是Integer.MAX_VALUE

这四种是阿里巴巴Java开发规范中所不推荐的,因为这四个线程池中,要么是最大线程数无界,要么阻塞队列无界,可能会造成OOM

推荐使用自定义的线程池,这样可以合理控制最大线程数和阻塞队列以及拒绝策略等

ThreadPoolExecutor中有几个重要的属性

自定义线程池

private static void customThreadPool() {ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());try {for (int i = 0; i < 90; i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + "\t 开始处理业务");});}} catch (Exception e) {e.printStackTrace();} finally {threadPool.shutdown();}}

参数说明

核心属性

int corePoolSize:核心线程数
int maximumPoolSize:允许创建的最大线程数
long keepAliveTime:空闲时间
TimeUnit unit:时间单位
BlockingQueue<Runnable> workQueue:任务队列
ThreadFactory threadFactory:线程池工厂
RejectedExecutionHandler handler:拒绝策略对于一个线程池来说,允许有 maximumPoolSize + workQueue.length 个任务提交过来,超过了这个阈值,就会触发拒绝策略private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
这个遍历的高三位保存的是线程池的状态,后29位保存的是线程池中工作线程的数量

线程池状态

/*** 运行状态,线程池刚创建就是这个状态* 高三位是111,低29位是0* 该状态会接收新的任务请求* 也会处理在阻塞队列中等待处理的任务*/private static final int RUNNING    = -1 << COUNT_BITS;/*** 停工状态,不再接收新任务,但是会处理已经在执行的和阻塞队列中的任务* 高三位为000,低29位为0,* 在running状态调用线程池的shutdown()方法,会从running变更为shutdown*/private static final int SHUTDOWN   =  0 << COUNT_BITS;/*** 停止状态,不再接收新任务,已有的任务也会中断,阻塞队列中的任务也不会再运行* 高三位为001,低29位为0*         在调用shutdownnow()方法之后,会从running/shutdown变更为stop状态*/private static final int STOP       =  1 << COUNT_BITS;/*** 清空状态,所有任务都停止了,工作的线程也全部结束了,workerCount为0* 高三位为010,低29位为0* 为此状态时,还将调用terminated()方法*/private static final int TIDYING    =  2 << COUNT_BITS;/*** 终止状态,线程池已经销毁;为此状态时还将调用terminated()方法* 高三位为100,低29位为0*/private static final int TERMINATED =  3 << COUNT_BITS;

拒绝策略:

1、AbortPolicy:直接抛出异常 RejectedExecutionException
2、CallerRunsPolicy:在调用方线程中执行任务
3、DiscardOldestPolicy:丢弃最先进入到队列中的任务,调用的是queue.offer()方法
4、DiscardPolicy:不做任务处理,其实丢弃的是当前任务

运行原理

    1. 创建线程池,等待请求过来2. 当调用了execute()方法添加一个请求任务之后,线程池会做如下判断:3. 1. 如果当前运行的线程数小于corePoolSize,那么会创建线程,运行这个任务2. 如果正在运行的线程数量大于或者等于corePoolSize,那么将这个任务加入队列3. 如果队列也满了,这时候运行的线程数还小于maximumPoolSize,就会创建非核心线程来运行这个任务4. 如果队列满了,且正在运行的线程数达到了maximumPoolSize,那么线程池会启动拒绝策略来执行4. 当一个线程的任务结束之后,会从队列中取下一个任务来执行5. 当一个线程空闲时间超过了keepAliveTime时,线程池会做以下判断:6. 如果当前运行的线程数超过了corePoolSize时,那么这个线程会被销毁,线程池中所有任务结束以后,线程数量会缩减到corePoolSize的大小

execute和submit的区别

1.入参不同,execute的入参只能是Runnable,submit的入参可以是Runnable,也可以是callable
2.submit有返回值,submit底层也是调用的execute,在调用execute的时候,会把入参包装成RunnableFuture
3.submit方便异常处理,如果task抛出了异常,那么通过future.get()可以捕获到异常信息

核心方法

1.Executor是线程池的基本接口,只有一个execute方法
2.ExecutorService是线程池Executor接口的子接口,额外提供了一些对线程池的其他操作:submit、shutdown等
3.AbstractExecutorService抽象类,实现了executorService的部分接口,比如:submit
4.ThreadPoolExecutor继承了AbstractExecutorService

获取线程池状态、工作线程数量

/*** 获取当前线程池的状态* @param c* @return*/private static int runStateOf(int c)     { return c & ~CAPACITY; }/*** 获取线程池活跃的数量* @param c* @return*/private static int workerCountOf(int c)  { return c & CAPACITY; }/*** 获取运行状态和活动线程数量的值* @param rs* @param wc* @return*/private static int ctlOf(int rs, int wc) { return rs | wc; }

runWorker()

执行提交的任务,这是比较核心的方法,在该方法中
1、先执行当前提交的任务
2、从任务队列中获取排队的任务
3、并执行

getTask()

这是从任务队列中获取排队任务的方法,在新增一个线程的时候,会先执行当前提交的任务,如果该任务执行完了之后,会从任务队列中尝试获取正在排队的任务,去依次执行

ThreadPoolExecutor源码学习(一) -核心属性及应用相关推荐

  1. ThreadPoolExecutor源码学习(2)-- 在thrift中的应用

    thrift作为一个从底到上除去业务逻辑代码,可以生成多种语言客户端以及服务器代码,涵盖了网络,IO,进程,线程管理的框架,着实庞大,不过它层次清晰,4层每层解决不同的问题,可以按需取用,相当方便. ...

  2. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)(转)

    阅读目录 一.MVC原理解析 1.MVC原理 二.HttpHandler 1.HttpHandler.IHttpHandler.MvcHandler的说明 2.IHttpHandler解析 3.Mvc ...

  3. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...

  4. 基于Qt5.14.2和mingw的Qt源码学习(三) — 元对象系统简介及moc工具是如何保存类属性和方法的

    基于Qt5.14.2和mingw的Qt源码学习(三) - 元对象系统简介及moc工具是如何保存类属性和方法的 一.什么是元对象系统 1.元对象系统目的 2.实现元对象系统的关键 3.元对象系统的其他一 ...

  5. 面试官系统精讲Java源码及大厂真题 - 37 ThreadPoolExecutor 源码解析

    37 ThreadPoolExecutor 源码解析 当你做成功一件事,千万不要等待着享受荣誉,应该再做那些需要的事. -- 巴斯德 引导语 线程池我们在工作中经常会用到.在请求量大时,使用线程池,可 ...

  6. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  7. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

  8. DotText源码学习——ASP.NET的工作机制

    --本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...

  9. Vuex源码学习(五)加工后的module

    没有看过moduleCollection那可不行!Vuex源码学习(四)module与moduleCollection 感谢提出代码块和截图建议的小伙伴 代码块和截图的区别: 代码块部分希望大家按照我 ...

  10. JAVA线程池(ThreadPoolExecutor)源码分析

    JAVA5提供了多种类型的线程池,如果你对这些线程池的特点以及类型不太熟悉或者非常熟悉,请帮忙看看这篇文章(顺便帮忙解决里面存在的问题,谢谢!):     http://xtu-xiaoxin.ite ...

最新文章

  1. CVPR 2020 论文大盘点-全景分割与视频目标分割篇
  2. ffmpeg 命令_ffmpeg常用命令行集锦
  3. 使用libjpeg进行图片压缩(哈夫曼算法,无损压缩)
  4. springboot整合mybatis增删改查(三):mybatis逆向工程
  5. Android中进度条控件使用
  6. 线程池java.util.concurrent.ThreadPoolExecutor总结
  7. yarn-cli 缓存(转)
  8. 教你如何优雅的改写“if-else”
  9. SpringBoot实战教程(7)| 整合JPA
  10. 会Python了不起吗?是的,简直开挂!(文末有福利)
  11. 移植基于Qt4.4-tp1的WebKit到ARM平台
  12. 小试牛刀——搭建一个周报管理系统
  13. Python3之正则表达式详解!
  14. c++智能指针转化:static_pointer_cast、dynamic_pointer_cast、const_pointer_cast、reinterpret_pointer_cast
  15. 利用python爬虫技术实现基于本福特定律_基于Python技术的校园网搜索引擎的设计与实现...
  16. Python Pandas缺省值(NaN)处理
  17. 谷歌搜索通告:疫情期间不要关站会影响网站排名
  18. 【点云系列】 场景识别类导读
  19. C#datagrid与datagridview的区别
  20. 他是硅谷最好斗的华人 微软、谷歌、特斯拉都离不开他

热门文章

  1. WWDC2019最值得看的十个视频
  2. lsd 特征点匹配代码_openCV-特征点匹配算法介绍一:理解特征
  3. java封装的注意事项_新手学习Java之对象---封装
  4. 剑指offer JZ02/05 替换空格 Python
  5. 图解tcpip 第5版 pdf_16G906国标图集,装配式混凝土剪力墙结构住宅施工图解,PDF版...
  6. 【DL小结3】RNN与LSTM
  7. 【概率论】期望、方差、协方差、相关系数、相关与独立、样本估计量、点估计、区间估计
  8. Matrix Cookbook 公式推导
  9. UTM(Undergraduate Texts in Mathematics)书单 |附下载链接
  10. Eclipse 中Access restriction: The type ‘XXX’ is not API