线程池核心原理剖析
Posted Java程序员社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池核心原理剖析相关的知识,希望对你有一定的参考价值。
一个应用中,如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?我们可以通过线程池来达到这样的效果。
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
当向线程池提交任务后,线程池会按下图所示流程去处理这个任务:
1)线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。
2)线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
3)线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
对应到代码层面就是ThreadPoolExecutor执行execute()方法。如下图所示:
1)如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。
2)如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。
3)如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。
4)如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。根据不同的拒绝策略去处理。ThreadPoolExecutor采取上述步骤的总体设计思路,是为了在执行execute()方法时,尽可能地避免获取全局锁(那将会是一个严重的可伸缩瓶颈)。在ThreadPoolExecutor完成预热之后(当前运行的线程数大于等于corePoolSize),几乎所有的execute()方法调用都是执行步骤2,而步骤2不需要获取全局锁。
如果你想进入大厂或者成为一名高级java开发,仅仅掌握线程池的原理是远远不够的。那么在实战中,究竟如何科学的使用线程池,线程池的源码又是如何一步一步实现上述功能的呢?
对此在10月19日20:00-22:00为大家准备了阿里P8级资深架构师玉峰老师的《JAVA开发实战——线程池底层原理剖析与实战》直播分享,24小时限时免费。玉峰将带你从原理+场景+案例,多维度剖析,全方位解读线程池的实现原理和实战技巧,助力全面提升。
限时免费直播,先到先得~
8年一线大厂经验,毕业后一直在阿里从事后端领域工作。在此期间,和「多隆」一起共事,深度参与多个实战项目,并担任核心负责人,相比一般人,对线程池的原理和使用有着更深刻和独到的理解。
注:本文所赠直播课程由爪哇教育独家友情赞助,爪哇教育致力于国内最优质的在线互联网人职业教育,核心成员以及所聘用的老师均来自BAT等一线大厂大牛,项目与实战经验7年以上,希望用更好的教育赋能更好的科技人才,为所有互联网从业者的升职加薪之路做最好的领路人。
以上是关于线程池核心原理剖析的主要内容,如果未能解决你的问题,请参考以下文章
线程池原理剖析
JDK线程池原理剖析
史上最清晰线程池实现原理剖析
高效开发:线程池的使用和基本原理剖析
线程池原理剖析
线程池原理剖析