前言
最近连续三天我们都在探讨线程池相关知识,因为过程讲的比较细,所以花的时间也比较久,不过昨天分享完成后,这块的内容也就基本结束了,今天我们就花一点时间做一个简单的总结,然后在总结之外,我们再把之前遗漏的知识点补充下。好了,话不多说,让我们直接开始吧!
线程池
今天的内容主要包括两个方面,一个就是总结,另一个就是查漏补缺,我们先说线程池的总结。
总结
关于总结的内容,我画了一个脑图(持续补充),所以总结就主要围绕这个脑图展开,这个脑图各位小伙伴可以在公众号聊天窗口输入【线程池】获取:
因为是总结,所以这一款的内容就不拖沓,只说知识点,想了解更详细的内容可以翻看最忌三天的推送内容。
构造参数
线程池有7
个构造参数:
corePoolSize
:核心线程数maximumPoolSize
:最大线程数keepAliveTime
:线程存活时间TimUnit
:线程存活时间的时间单位workQueue
:工作队列ThreadFactory
:线程工厂RejectedExecutionHandler
:拒绝策略处理器
构造方法
线程池有四个构造方法:
- 基本构造方法:前五个参数(那天我说就三个,我是没算存活时间和存活时间的时间单位)
- 工厂构造方法:前五个参数
+
线程工厂 - 策略构造方法:前五个参数
+
拒绝策略处理器 - 全套构造方法:所有参数都有
常用方法
execute
:执行多线程任务,没有返回值submit
:执行多线程人,有返回值的,父类方法shutdown
:关闭线程池
其他方法
prestartCoreThread
:预启动一个核心线程,如果核心线程都已经启动就没啥用了prestartAllCoreThreads
:预启动所有核心线程,如果核心线程都启动这个方法也一样没有用shutdownNow
:立即关闭线程池,关于它和shutdown
的区别,我们后面补充说明isShutdown
:线程池是否已关闭,如果执行过shutdown
或者shutdwonNow
,则该方法值为true
isTerminating
:线程池是否正在停止,执行过关闭方法后,但线程池未完全停止,该方法值为true
isTerminated
:线程池彻底关闭后该方法值为true
purge
:移除工作队列中所以被取消的任务remove
:移除工作队列中的任务
核心知识点
- 线程池能够处理的最大任务数 =
corePoolSize + maximumPoolSize + workQueue
- 向已经达到最大任务处理数线程池提交新的任务时,会触发
RejectedExecutionHandler
的rejectedExecution
方法 RejectedExecutionHandler
的rejectedExecution
方法如果抛出RejectedExecutionException
会导致核心线程阻塞- 如果不指定
RejectedExecutionHandler
,系统会指定默认的处理器AbortPolicy
,默认处理器会直接抛出RejectedExecutionException
- 线程池在创建后是没有线程的,线程是在
execute
方法执行后才创建的 - 可以通过
prestartCoreThread
或者prestartAllCoreThreads
方法来初始化线程池,也就就是预创建核心线程 - 线程池使用完成后必须关闭,否则会阻塞后续操作
- 在核心线程没有完全启动完,每次
execute
都会创建新的线程 - 线程池最大线程数只能大于等于核心线程数
- 当任务数大于核心线程数+工作队列大小时,若最大线程数大于核心线程数,则会继续创建线程,直到线程数达到最大线程数
- 线程存活时间只对核心线程之外的线程资源起作用,它在工作队列为空时起作用,延缓核心线程之外的线程资源的销毁
- 线程池关闭后便再无法继续接受任务,如果关闭后继续执行
excute
方法会调用rejectedExecution
方法
补充知识
shutdown
和shutdownNow
shutdown
执行后会等待所有已经提交的线程执行完成,执行之后,只是不能再接受新的任务,shutdwonNow
会尝试关闭所有正在执行的任务,同时会取消正在等待的任务,会返回未执行完成的任务。
下面是他们的内部实现:
prestartCoreThread
和prestartAllCoreThreads
我们前面说了,正常情况下,线程启动是在execute
方法或者sumbit
方法执行的时候启动的,但是我们也可以提前启动核心线程池中线程。
prestartCoreThread
是预启动一个核心线程,当然前提条件是核心线程数未达到核心线程数上线,prestartAllCoreThreads
是启动所有的核心线程,前提条件是一样的。
其他补充内容
其实线程池这块至少还有三块内容需要补充,一个是工作队列,一个是拒绝策略器,另一个就是系统常用的线程池的实现机制,但是我暂时不打算分享了,这块的内容看着不多,但是如果真要分享的话,至少需要分三次才能彻底搞完;
另外一个考虑的是,不能我把什么都讲完,要给大家留一点内容供大家自学;
最后一个原因是,最近天天都是线程池,有点上头,稍事休息下,毕竟周末也不能太卷了
总结
其实今天通篇就是在总结,所以总结的话就没必要多说了,但是还是想从个人学习经验这块多叨叨两句。
学习这件事最重要的还是要主动,要多动手。对我来说,我之前对多线程的认识仅仅是停留在会用,只知道一些常用的方法,但是对于它内部的原理和实现机制,一直是不求甚解的,但是呢,通过最近这三四天,我现在已经对线程池有了更系统的认知和了解,而且也更清楚线程池实际使用的潜在问题,以及如何避免这些问题,这就是我学习的意义。
当然更深远的意义是结合自己之前遇到的一些线上问题,我发现原来如果我能早点知道这些知识,那我可以少走很多弯路,这大概就是成长吧——技术有了积累,眼界得到开阔,未来才能走更远……
好了,最后希望所有小伙伴都能找到适合自己的学习之路,能够在自己的努力下,得到自己期待的东西……周末快乐鸭!