Java 并发系列(一) ThreadPoolExecutor源码解析及理解
// ctl非常重要,用整型表示,共32位,其中**高3位代表线程池状态,低29位代表工作线程数**;
// 线程池状态初始化为RUNNING,工作线程数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); // 偏移量29
private static final int COUNT_BITS = Integer.SIZE - 3; // 理论最大线程数(约500万)
private static final int CAPACITY = (1 << COUNT_BITS) - 1; // -1左偏移29位(下同),运行中状态,既能接收新提交的任务,又能执行阻塞队列中的任务
private static final int RUNNING = -1 << COUNT_BITS; // 关闭状态,不再接收新提交的任务,但还能继续执行阻塞队列中的任务(调用shutdown()可以进入此状态)
private static final int SHUTDOWN = 0 << COUNT_BITS; // 停止状态,不再接收新提交的任务,也不再执行队列中的任务;而且会尝试中断正在执行的工作线程(调用shutdownNow()可以进入此状态)
private static final int STOP = 1 << COUNT_BITS; // 清理状态,当workCount(工作线程数)为0,且队列也为空时就是此状态
// SHUTDOWN -> TIDYING 线程数为0,队列也为空时会自动进入改状态
// STOP -> TIDYING 线程数为0时,就会自动进入该状态
private static final int TIDYING = 2 << COUNT_BITS; // 终结状态 可以通过调用awaitTermination方法来来等待线程池彻底终结
private static final int TERMINATED = 3 << COUNT_BITS; // 获取线程池运行状态;因为CAPACITY为29个1,取反后是29个0,再通过&运算会取出最高的3位
private static int runStateOf(int c) { return c & ~CAPACITY; } // 获取线程池中线程数;取出最低的29位
private static int workerCountOf(int c) { return c & CAPACITY; } // 将运行状态与线程数拼接起来,共有恰好有32位(因为rs已经左偏移29位了!)
private static int ctlOf(int rs, int wc) { return rs | wc; }
2. 核心构造方法
/*
* 1. 共有7个参数
* 2. 具体实现不再细说,只简单说下各个作用(就是使用流程)
* corePoolSize: 核心线程数,如果总工作线程数小于核心线程数, 有新任务时则会继续创建新的线程
* maximumPoolSize: 最大线程数,理论上包含了核心线程数和非核心线程数
* keepAliveTime: 一般上(allowCoreThreadTimeOut=false)是指非核心线程没有任务执行的存活时间(可以通过getTask()方法去分析)
* TimeUnit: keepAliveTime的时间单位
* workQueue: 阻塞队列,其中包含有SynchronousQueue, ArrayBlockingQueue, LinkedBlockingQueue; 存放核心线程执行不过来时被提交的任务
* threadFactory: 线程工厂,创建线程的地方
* handler: 拒绝策略,线程池满时会执行该策略rejectedExecution()方法;自带有4种拒绝策略,默认使用抛异常拒绝策略,另有什么都不做策略,用调用者线程执行任务策略,抛弃最旧任务策略
*
* 注意:1. 核心线程和非核心线程只是个逻辑的概念,某个线程被创建后,一开始可能是核心的,到后来会变成非核心的,身份并不固定。(看具体getTask()时会不会得到null)
* 2. 流程归总:当新任务被提交后,当工作线程数小于核心核心线程数时,会继续创建线程来处理此任务,否则会将其放在阻塞队列中;若阻塞队列已满,则会创建线程来处理此任务;若创建线程失败(不小于了最大线程数),则会执行拒绝策略。
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
3. 疑问
Java 并发系列(一) ThreadPoolExecutor源码解析及理解的更多相关文章
- Java并发系列[10]----ThreadPoolExecutor源码分析
在日常的开发调试中,我们经常会直接new一个Thread对象来执行某个任务.这种方式在任务数较少的情况下比较简单实用,但是在并发量较大的场景中却有着致命的缺陷.例如在访问量巨大的网站中,如果每个请求都 ...
- 死磕 java同步系列之Phaser源码解析
问题 (1)Phaser是什么? (2)Phaser具有哪些特性? (3)Phaser相对于CyclicBarrier和CountDownLatch的优势? 简介 Phaser,翻译为阶段,它适用于这 ...
- 死磕 java同步系列之ReentrantReadWriteLock源码解析
问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...
- Java并发系列[2]----AbstractQueuedSynchronizer源码分析之独占模式
在上一篇<Java并发系列[1]----AbstractQueuedSynchronizer源码分析之概要分析>中我们介绍了AbstractQueuedSynchronizer基本的一些概 ...
- Java并发系列[3]----AbstractQueuedSynchronizer源码分析之共享模式
通过上一篇的分析,我们知道了独占模式获取锁有三种方式,分别是不响应线程中断获取,响应线程中断获取,设置超时时间获取.在共享模式下获取锁的方式也是这三种,而且基本上都是大同小异,我们搞清楚了一种就能很快 ...
- Java并发系列[5]----ReentrantLock源码分析
在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...
- 死磕 java同步系列之CyclicBarrier源码解析——有图有真相
问题 (1)CyclicBarrier是什么? (2)CyclicBarrier具有什么特性? (3)CyclicBarrier与CountDownLatch的对比? 简介 CyclicBarrier ...
- 死磕 java同步系列之StampedLock源码解析
问题 (1)StampedLock是什么? (2)StampedLock具有什么特性? (3)StampedLock是否支持可重入? (4)StampedLock与ReentrantReadWrite ...
- 死磕 java同步系列之Semaphore源码解析
问题 (1)Semaphore是什么? (2)Semaphore具有哪些特性? (3)Semaphore通常使用在什么场景中? (4)Semaphore的许可次数是否可以动态增减? (5)Semaph ...
- 死磕 java同步系列之ReentrantLock源码解析(二)——条件锁
问题 (1)条件锁是什么? (2)条件锁适用于什么场景? (3)条件锁的await()是在其它线程signal()的时候唤醒的吗? 简介 条件锁,是指在获取锁之后发现当前业务场景自己无法处理,而需要等 ...
随机推荐
- github|webstorm
分享本地项目到github 从github上迁出项目到本地
- web前端要学哪些?
本来是学java还有jsp这些东西的,后来毕业了就去找了个前端的工作:一开始就接触 nodejs+express+Angularjs+mongodb这些东西.不知道学了这些东西做前端够不够用.现在也就 ...
- 福大软工1816:Beta(5/7)
Beta 冲刺 (5/7) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务 文字/口头描述 组织会议 确定统一界面wxpy.db之 ...
- Vue-学习。
---恢复内容开始--- Vue.js 与 Angular.js 非常相似,只要学过了Angular.js然后在学Vue.js就非常的简单. 什么是Vue? 相比Angularjs和ReactJS,V ...
- Django之自定义权限
官方解释 Custom permissions¶ To create custom permissions for a given model object, use the permissions ...
- Jboss Jmx-Console和 Jboss web-console安全设置
1.介绍 如果你暴露你的JBoss服务器通过网络(如通过启动服务器使用选项B 0.0.0.0或者通过改变jboss.bind.address首次出现0.0.0.0在.../jboss/server/d ...
- MySQL8.0初体验
MySQL8.0的官方社区开源版出来有段时间了,而percona的8.0版本还没有正式对外发布(已发布测试版),一直以来也没安装体验下这个号称质的飞跃的版本,今天正好有些时间就下了安装体验体验. 一. ...
- FileStream对文本进行读写操作
class FileHelper { /// <summary> /// 检验文件路径是否合法 /// </summary> /// <param name=" ...
- Shell: extract more from listener.log (分析oracle监听日志)
最近遇到了两起数据库连接数不足的问题, 通常都会预留一些会话增加的情况, 但在一些特殊情况下如连接风暴(logon storm), 如果在监听中没有做rate限流,对数据库来说巨大的冲击可能会导致数据 ...
- 卸载oracle 10g
1.开始->设置->控制面板->管理工具->服务——> 停止所有Oracle服务.(没有起动的就不用停用了)2.开始->程序->Oracle - OraD ...