7000字+24张图带你彻底弄懂线程池(三)

pivoteic
发布于 2022-6-17 16:50
浏览
0收藏

 

说完整个执行的流程,接下来看看execute方法代码是如何实现的。

7000字+24张图带你彻底弄懂线程池(三)-鸿蒙开发者社区

  • workerCountOf(c)<corePoolSize:这行代码就是判断是否小于核心线程数,是的话就通过addWorker方法,addWorker就是添加线程来执行任务。
  • workQueue.offer(command):这行代码就表示尝试往阻塞队列中添加任务
  • 添加失败之后就会再次调用addWorker方法尝试添加非核心线程来执行任务
  • 如果还是添加非核心线程失败了,那么就会调用reject(command)来拒绝这个任务。

 

最后再来另画一张图总结execute执行流程

7000字+24张图带你彻底弄懂线程池(三)-鸿蒙开发者社区

四、线程池中线程实现复用的原理

 

线程池的核心功能就是实现了线程的重复利用,那么线程池是如何实现线程的复用呢?

 

线程在线程池内部其实是被封装成一个Worker对象

7000字+24张图带你彻底弄懂线程池(三)-鸿蒙开发者社区

Worker继承了AQS,也就是有一定锁的特性。

 

创建线程来执行任务的方法上面提到是通过addWorker方法创建的。在创建Worker对象的时候,会把线程和任务一起封装到Worker内部,然后调用runWorker方法来让线程执行任务,接下来我们就来看一下runWorker方法。

7000字+24张图带你彻底弄懂线程池(三)-鸿蒙开发者社区

从这张图可以看出线程执行完任务不会退出的原因,runWorker内部使用了while死循环,当第一个任务执行完之后,会不断地通过getTask方法获取任务,只要能获取到任务,就会调用run方法,继续执行任务,这就是线程能够复用的主要原因。

 

但是如果从getTask获取不到方法的时候,最后就会调用finally中的processWorkerExit方法,来将线程退出。

 

这里有个一个细节就是,因为Worker继承了AQS,每次在执行任务之前都会调用Worker的lock方法,执行完任务之后,会调用unlock方法,这样做的目的就可以通过Woker的加锁状态就能判断出当前线程是否正在运行任务。如果想知道线程是否正在运行任务,只需要调用Woker的tryLock方法,根据是否加锁成功就能判断,加锁成功说明当前线程没有加锁,也就没有执行任务了,在调用shutdown方法关闭线程池的时候,就用这种方式来判断线程有没有在执行任务,如果没有的话,来尝试打断没有执行任务的线程。

 

文章转自公众号:三友的java日记

标签
已于2022-6-17 16:50:54修改
收藏
回复
举报
回复
    相关推荐