深入解析线程池底层原理

本文详细介绍了线程池的实现原理,包括线程池状态、初始化、任务执行、等待队列策略、拒绝策略、关闭与容量调整。分析了线程池的ctl字段如何用32位表示状态和线程数,以及如何通过位运算获取状态和数量。还探讨了线程池的初始化、执行任务的步骤,特别是`addWorker()`方法。此外,文章还讨论了自定义钩子方法、四种拒绝策略、四种等待队列类型以及如何配置线程池大小,推荐使用利特尔法则进行精细化调整。
摘要由CSDN通过智能技术生成

本期内容会从以下几个方面解析线程池的具体实现:

  • 线程池状态
  • 线程池初始化
  • 如何执行任务
  • 钩子方法
  • 等待队列和排队策略
  • 自定义拒绝策略
  • 线程池关闭
  • 动态调整容量
  • 合理配置容量

线程池状态

 

ThreadPoolExecutor中定义了如下几种线程池状态:

  • RUNNING :运行状态,该线程池可以接受新任务和处理排队任务
  • SHUTDOWN:关闭状态,不接受新任务,但处理排队任务
  • STOP:停止状态,不接受新任务、不处理排队任务和中断进行中任务
  • TIDYING:整理状态,所有的线程任务已终止,workerCount为零,转换到整理状态的线程将运行terminated()钩子方法
  • TERMINATED:终止状态,terminated()执行完毕,线程池将会被设置为TERNINATED状态。

我们在上面代码中看到了对于线程池状态的定义,但是并没有发现有定义一个int类型的变量表示当前线程池的状态,那是怎么做的呢?

我们看到在最上面有定义一个AtomicInteger ctl这样一个原子类型的Integer,这个ctl不光可以表示线程池的运行状态,同时能够表示线程池的有效线程数workerCount。那么是怎么做到的呢?我们都知道Integer类型的内存大小是4个字节,对应32个bit,ctl将32位的高三位用来表示线程池的运行状态,低29位表示有效线程数。

这里可以想一下为什么是用高三位表示runState,不是两位,也不是4位呢?

因为线程池的状态定义了5种,而二进制要能够表示5种值最少要用3位。比如1位只能表示0和1,两位能表示00/01/10/11四种,那3位能表示的值则是2^3也就是8种,所以要标识5种状态则最少需要3位。

因为这一点,也限制了一个线程池理论上能设置的最大线程数是2^29-1个。

那如果想要从这一个字段里取出runState或者workCount的值应该怎么做的?

可以看到是通过位运算来实现的。这里先给大家插播一下位运算的逻辑。

  • 按位与&:两数同为1则为1,其他情况为0,如0101& 0100 的结果是0100
  • 按位或|:两数只要有1个是1,则为1,如 0101|0100的结果是0101
  • 按位取反~:0变1,1变0,如0101按位取反则等于1010

要获取高位的runState则使用ctl的值c和容量&#

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倾听铃的声

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值