在使用线程池的时候,我们会使用到提交线程池的方法execute()。

 public void execute(Runnable command) {e.execute(command); }

它的主要作用是提交执行任务,参数支持Runnable, execute()没有返回值,同时,它的任务里必须捕获异常。
execute()的工作主要流程如下图所示:

接下来就主要去看看这个execute()方法的源码含义
1.当传入一个 null的 Runnable的时候,会进行抛出异常

 if (command == null)throw new NullPointerException();

2.获取最新的ctl值

 int c = ctl.get();

3.进行了一次 workerCountOf© 和当前线程池核心数的比较,如果true,则可以提交此次线程数量,进行创建一个worker

 if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}

4.再往下走,表示addworker失败了,或者当前线程数量 > corePoolSize,进入到方法后,再次获取最新的数量

 if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}

5.最后都不满足条件的话,走到了最后一个条件,表明当前线程池是非Running状态

 else if (!addWorker(command, false))reject(command);

该方法的具体描述如下:

    public void execute(Runnable command) {if (command == null)throw new NullPointerException();/** Proceed in 3 steps:** 1. If fewer than corePoolSize threads are running, try to* start a new thread with the given command as its first* task.  The call to addWorker atomically checks runState and* workerCount, and so prevents false alarms that would add* threads when it shouldn't, by returning false.** 2. If a task can be successfully queued, then we still need* to double-check whether we should have added a thread* (because existing ones died since last checking) or that* the pool shut down since entry into this method. So we* recheck state and if necessary roll back the enqueuing if* stopped, or start a new thread if there are none.** 3. If we cannot queue task, then we try to add a new* thread.  If it fails, we know we are shut down or saturated* and so reject the task.*/// c : 获取ctl最新值int c = ctl.get();// workerCountOf(c) 获取当前线程的数量 true: 表示当前线程数量 < 核心线程数量// 表示此次提交线程数量,直接创建一个新的 worker.if (workerCountOf(c) < corePoolSize) {// core == true 表示采用核心线程数量限制 false 表示采用 maximumPoolSizeif (addWorker(command, true))// 创建成功后, 直接返回return;// 创建失败:// 1.存在并发现象// 2.当前线程池状态发生了改变 Running SHUTDOWN STOP TIDYING , 当线程池状态非Running 会失败// 3.c = ctl.get();}// 执行到这里的情况:// 1.当前线程数达到了 corePoolSize// 2. addWorker失败了if (isRunning(c) && workQueue.offer(command)) {// 再次获取ctl的最新值int recheck = ctl.get();// 条件一:  ! isRunning(recheck) 成立: 说明你提交到队列之后,线程池状态被外部修改了// 条件二:  remove(command); true: 提交之后,线程池中的线程还未被消费if (! isRunning(recheck) && remove(command))// 提交之后,线程池状态为非Running , 且任务出队成功,reject(command);//  workerCountOf(recheck)为 true:else if (workerCountOf(recheck) == 0)addWorker(null, false);}// 执行到这里的情况// 1. offer() 失败// 2.当前线程池是非Running状态// 1.else if (!addWorker(command, false))reject(command);}

线程池的设计与原理解析(二)之---execute()方法相关推荐

  1. 你还不懂线程池的设计及原理吗?掰开揉碎了教你设计线程池

    大家在学习线程池的时候也曾查阅过各种资料,但是感觉大佬写的很好但是写的不够详细,写的详细的设计思路又很简单,所以我的出发点就是让读者可以清晰明确的看懂整个设计思想和设计过程,可以举一反三,在今后内存池 ...

  2. java 线程池的使用及原理(二):线程池的状态及证明

    线程的状态具有运行与关闭的状态,那么线程池也不例外.java线程池具有 5 种状态:Running.ShutDown.Stop.Tidying.Terminated. 线程池状态解析 1. Runni ...

  3. 线程池的设计(二):领导者追随者线程池的设计

    2019独角兽企业重金招聘Python工程师标准>>> 接上文:线程池的设计(一):半同步半异步线程池的设计 领导者追随者模式在使用方式上与半同步半异步模式相同,以下主要介绍不同的实 ...

  4. java 中线程池的种类,原理以及源码解析(1)

    java 中的线程池创建都是Executors 类中提供的方法,并且方法返回线程池对象. Executors 源码: // // Source code recreated from a .class ...

  5. 【重难点】【JUC 05】线程池核心设计与实现、线程池使用了什么设计模式、要你设计的话,如何实现一个线程池

    [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计的话,如何实现一个线程池 文章目录 [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计 ...

  6. 线程池的优点及其原理,代码实现线程池。简单、明了。

    一 使用线程池的好处 池化技术应用:线程池.数据库连接池.http连接池等等. 池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率. 线程池提供了一种限制.管理资源的策略. 每个线程池 ...

  7. 【C++ 并发 线程池设计】深入理解C++线程池:设计、实现与应用

    目录标题 1. 引言 2. 线程池类设计 2.1 线程池类的主要成员变量 2.2 线程池类的构造函数和析构函数 3. 线程池任务的添加与执行 3.1 如何添加任务到线程池 3.2 如何在线程池中执行任 ...

  8. 游戏线程池的设计0-转自

    游戏线程池的设计 在前面的章节中,我们一再提到,游戏的业务逻辑复杂, 很多数据都是放在内存中进行处理的,但是,仅仅放在内存中还不能完全满足要求. 我举个例子,房间 A 里面的四个玩家打牌,如果使用普通 ...

  9. 【开源项目】动态线程池框架Hippo4j源码解析

    动态线程池框架Hippo4j源码解析 项目简介 Hippo-4J 通过对 JDK 线程池增强,以及扩展三方框架底层线程池等功能,为业务系统提高线上运行保障能力. 快速开始 https://hippo4 ...

  10. JAVA线程池 -clt设计与分析

    1. 前言 ctl 是线程池源码中常常用到的一个变量. 它的主要作用是记录线程池的生命周期状态和当前工作的线程数. 作者通过巧妙的设计,将一个整型变量按二进制位分成两部分,分别表示两个信息. 2. 源 ...

最新文章

  1. 1035 Password
  2. 某程序员吐槽:妈妈到处炫耀自己年薪三十万,老家亲戚纷纷向自己借钱,已借出十几万!怎么办?网友:反借回去!...
  3. 自然归并排序 c++ (原创)
  4. 从源码角度看Android系统SystemServer进程启动过程
  5. 在TensorFlow和PaddleFluid中使用多块GPU卡进行训练
  6. POJ 1696 Space Ant 极角排序(叉积的应用)
  7. 两个用于Eclipse的TCK –开源到底有什么?
  8. 远程服务器 上传公钥,SSH远程连接报错Permission denied (publickey)
  9. Ubuntu 16.04中zabbix4.2设置中文显示
  10. 【LaTeX】LaTeX安装美赛模板(mcmthesis)使用笔记(含代码)
  11. MAC 迅雷最新版无限重启BUG的解决方法
  12. 北京科技大学计算机博士统考,北京科技大学计算机与通信工程学院2016年博士录取方案...
  13. Java程序员必备的网盘资源 大集合
  14. c++求余弦的泰勒展开式
  15. ?username=王二麻子age=18转换成对象?
  16. 【群晖NAS】真·免费内网穿透方案 及踩坑合集
  17. 产品分型面、插靠破、潜水进胶注意事项!
  18. 哥德尔:伟大的数学家与饱受精神疾病折磨的患者
  19. 输入一个一维数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。
  20. 中国成最大工业机器人市场 年增长速度25%

热门文章

  1. 前后端分离开发,如何定义各类错误码?
  2. 【iOS】通过URL Scheme启动app(收集了常用的app的URL Scheme)
  3. 苹果无需越狱(iPhone、iPad)手机多开教程
  4. 马未都说收藏:陶瓷篇(18、19)五彩瓷、斗彩
  5. java基础—输入/输出
  6. CoreDNS篇7-性能压测
  7. 略谈“10步天才(10 step)思维模型”
  8. 小程序开发有哪些方式?
  9. scala时间处理-获取今天日期,昨天日期,本周时间,本月时间,时间戳转换日期,时间比较
  10. 股份制的起源—严谨版与趣味版