线程池ThreadPoolExecutor的内部类Worker的感想和思考

2020-08-08T00:43:39
关注公众号【好便宜】( ID:haopianyi222 ),领红包啦~
阿里云,国内最大的云服务商,注册就送数千元优惠券:https://t.cn/AiQe5A0g
腾讯云,良心云,价格优惠: https://t.cn/AieHwwKl
搬瓦工,CN2 GIA 优质线路,搭梯子、海外建站推荐: https://t.cn/AieHwfX9

Worker依然是一个Runnable,封装了一个创建自己的原因对象,就是firstTask变量,和自己将要执行的所在线程thread变量。

thread成员变量可以直接被外部类ThreadPoolExecutor所获得,当调用addWorker方法时,会获得这个thread对象,从而启动成为真正的线程。然后,这个线程开始执行Worker的run方法,run方法直接调用其外部类ThreadPoolExecutor的方法runWorker,这个runWorker因为要前后会执行提供给子类自己完善的模板方法beforeExecute和afterExecute,也许这个是为什么worker要直接执行外部类方法的一个原因吧。但我猜想,不是这么简单。

首先runWorker会把产生创建自己的原因的任务给先执行了,然后,开始while((task == getTask()) != null)的无线循环下去,而getTask方法依然还是外部类ThreadPoolExecutor的方法,原来,runWorker的调用,用意是将代码的执行流程带到自己的方法流程上。

getTask()方法,是个无线循环方式从workQueue尝试拉取任务来执行,但为什么要做那么多额外的工作呢?一般人写拉取阻塞队列的对象,无非就是无限循环的workQueue.poll()吗?为什么jdk里面的实现里面有这么多代码呢?

因为有keepalive参数的设置,所以,顶多改写成workQueue.poll(keepalive,TimeUnit.SECONDS)。

我们想一想,能够让getTask方法返回的原因就哪些?

1.超过keepalive的时间,返回空任务,此时runWorker方法结束调用。

2.线程池被关闭,此时,响应中断。

原来就一个参数可以控制是否使用keepalive参数,这个参数是allowCoreThreadTimeOut,其他额外的代码应该就是为了这个参数服务的。其实为了正确的停止线程池发出的shutdown命令的。

我们来看shutdown方法,

首先加锁? 

然后调用checkShutdownAccess方法,尝试检测是否具有停止线程的权限和访问线程的权限,若存在,则执行下面的一个方法调用,否则,直接就解锁返回方法调用了。

然后调用advanceRunState修改线程池的状态位shutown

然后调用interruptIdleWorkers方法,传递参数为false,也就是并非只打断一个线程,开始打断所有空闲的worker线程,此时若有空闲的线程,应该是阻塞在workQueue.poll或workQueue.take方法调用处,

Worker对象的实现AbstractQueuedSynchronizer类,意在是自己能够具有类似锁的能力,其实就是标识自己是否是空闲线程,当一个工作线程获得任务,那么我们让它在执行自己的业务代码之前加锁,其他线程判断它是否忙碌,只要调用tryLock就可以知道,如果tryLock返回true,那么就说明这个线程是空闲线程,若返回false,则说明不是,因为工作线程没有执行完自己的业务代码。为什么直接继承这个AbstractQueuedSynchronizer类,而不是使用其他重入锁,因为就是想获得互斥的能力,而不想具有重入的能力。

线程的执行方式,以来线程的停止方式。

扫一扫关注公众号添加购物返利助手,领红包
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »
因本文不是用Markdown格式的编辑器书写的,转换的页面可能不符合MIP标准。