线程池

添加任务的规律

先核心,再任务队列,再非核心,再饱和策略

 

有哪些饱和策略

(default)throw exception

run

{}

queue.poll,再次execute

 

正确关闭

(具体可以看https://blog.csdn.net/zaozi/article/details/38854561

最正确的还是通过打标记位,不过interrupt是系统默认替我们实现的标记位。我们只需要在线程运行的时候,时不时去检测这个标记位即可。然后future的关闭其实也是一样的,和runnable没啥区别。

 

梳理下比较重要的源码流程

从execute入手,第一时间看见的就是我们的核心规则:先核心线程,再队列,再非核心线程,再饱和策略。其中核心线程和非核心线程的增加是通过addWorker方法来的,首先会有一个双重for循环配合cas与retry实现worker count+1。然后会加悲观锁,创建worker,创建成功后,启动线程。然后会执行worker的runWorker方法,首先会执行我们第一个加进去的任务,然后会进入无限循环,条件是getTask,如果队列中没有任务了,会阻塞在取元素的方法上。如果有新任务到来,会唤醒取元素的方法。这就是线程复用的奥秘。

 

为什么Worker要继承AQS?他是怎么应用AQS的特性的?

其实worker已经几乎无异于一个独占锁了。提供了lock与unlock方法,和reentrantlock极其地相似。他不期望worker的线程在执行任务的时候,外部线程来中断任务。因此worker在执行任务之前,会worker.lock,在执行任务之后,会worker.unlock。同时在interrupt方法中,在中断每个worker之前都会worker.trylock,在调用thread.interrupt方法后,会worker.unlock。这样可以实现比如在中断一个worker的过程中,任务执行处阻塞在worker.lock处,在中断一个worker后,执行worker.unlock,因此任务执行处被唤醒,得以继续执行。而任务在lock的时候,trylock会返回false,直接不中断这个worker了。

这样就实现了interrupt idle workers的功能。

但是为什么一定要让Worker继承AQS来实现清理空闲任务的功能呢?有没有另外的更好的实现?

理一下思路,如果我们要实现这个功能

1.检测他是空闲的

2.然后置为正在中断中,避免他进入工作状态

显然需要用cas

我们在thread.interrupt后,希望让他继续工作状态

那么显然lock是最好的,他要进入工作状态的时候,检测到正在中断中,阻塞;然后unlock一下,让他继续执行

同时他在执行的时候,我需要检测他的工作状态,然后尝试置为正在中断中

显然也要cas

然后如果失败,就不中断这个执行任务中的线程了。

任务执行完后,unlock,这样才有机会trylock成功。

再问,用reentrantlock代替行不行?

那么我中断的时候,就不再是trylock了,而是lock,这也意味着我在尝试中断的时候,检测到线程正在运行,那么我会阻塞,而不是跳过。显然reentrantlock实现不了这个操作,而且他也不开放tryLock这个api。

 

//说错了,是中断,而不是清理(必须能够响应中断才能在中断的时候被清理)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值