在runWorker有一段代码,就是工作线程中止的重要代码:
final void runWorker(Worker w) { ... while (task != null || (task = getTask()) != null) { if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); task.run(); } ... }重点关注:
if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt();这个if看起来有点难理解,理解下来大致意思是:如果线程池状态大于等于STOP,立即中断线程,否则清除线程的中断标记,也就是说当线程池状态为RUNNING和SHUTDOWN时,线程的中断标记会被清除(线程的中断代码在interruptWorkers方法中),可以继续执行任务。
以上代码执行完成后,紧接着就会调用task.run()方法,这里面我们自己就可以根据线程的中断标记来判断任务是否被中断。
总结个人水平有限,文中如有错误,谢谢大家指正。
本文从线程池的源码入手,分析线程池的创建、添加任务、运行任务等流程,整个分析下来基本上大多数公司关于线程池面试的问题都可以回答得上来,当然还有一些小细节如:Worker类是继承AQS的,为什么这么做其实源码中都有一些苗头,Worker在运行时会锁住运行的代码块,而shutdown在关闭空闲的Worker时,首先就要去获取Worker的同步锁才能继续操作,这样才能安全的关闭工作线程。
欢迎关注我的公众号:架构文摘,获得独家整理120G的免费学习资源助力你的架构师学习之路!
公众号后台回复arch028获取资料: