线程池管理器(ThreadPool)
:用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
工作线程(PoolWorker)
:线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
任务接口(Task)
:每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
任务队列(taskQueue)
:用于存放没有处理的任务。提供一种缓冲机制
。
当线程池中有任务需要执行时,线程池会判断如果池里的线程数没有占满
就会新建线程池进行任务执行,如果线程池中的线程数量已经超过核心线程数,这时候任务就会被放入任务队列中排队等待执行;如果任务队列也满了,并且线程池没有达到最大线程数,就会新建非核心线程
来执行任务;如果超过了最大线程数,就会执行饱和策略(拒绝执行)
。
不同点
连接池:
-
连接池是
面向数据库连接的
-
连接池是为了优化数据库连接资源
-
连接池有点类似在客户端做优化
数据库连接是一项有限的昂贵资源,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的性能低下。
数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由应用程序动态地对池中的连接进行申请、使用和释放
。对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。
线程池:
-
线程池是
面向后台程序的
-
线程池是是为了提高内存和CPU效率
-
线程池有点类似于在服务端做优化
线程池是一次性创建一定数量的线程(应该可以配置初始线程数量的),当用请求过来不用去创建新的线程,直接使用已创建的线程,使用后又放回到线程池中。
避免了频繁创建线程,及销毁线程的系统开销,提高是内存和CPU效率。
相同点
都是事先准备好资源,避免频繁创建和销毁的代价
。
感谢小梅!希望各位程序员在沉淀多年后,也能绽放出自己美丽的时刻,实现自身价值。一起淦(juǎn)
作者:小梅同学
========================================================================================
分析一般从几个角度考虑:
-
任务的性质:CPU密集型的任务、IO密集型任务、混合型任务。
-
任务的优先级:高、中、低
-
任务执行时间:长、中、短
-
任务的依赖性:是否依赖其它系统资源,如数据库的连接等。
cpu密集型
尽量减少线程数;比如像加解密,压缩、计算等一系列需要大量耗费 CPU 资源的任务,大部分场景下都是纯 CPU 计算。尽量使用较小的线程池
,一般为CPU核心数+1
。因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,会造成CPU过度切换
。
IO密集型
任务尽量加大线程数,因为io不占用cpu的资源。比如像 MySQL 数据库、文件的读写、网络通信等任务,这类任务不会特别消耗 CPU 资源,但是 IO 操作比较耗时,会占用比较多时间。可以使用稍大的线程池,一般为CPU核心数 * 2
。IO密集型任务CPU使用率并不高
,因此可以让CPU在等待IO的时候有其他线程去处理别的任务,充分利用CPU时间。
混合型
尽量根据实际情况进行拆分,根据运行时间来决定。
可见,线程的平均工作时间所占比例越高,就需要越少的线程;线程的平均等待时间所占比例越高,就需要越多的线程;
当线程池中核心线程数量过大时,线程与线程之间会争取CPU资源,这样就会导致上下文切换。过多的上下文切换会增加线程的执行时间,影响了整体执行的效率;
多线程编程中一般线程的个数都大于CPU核心的个数,而一个CPU核心在任意时刻只能被一个线程使用,为了让这些线程都能得到有效的执行,CPU采取的策略是为了每个线程分配时间片并轮转的形式。当一个线程的时间片用完的时候就会重新处于就绪状态让其他线程使用,这个过程就属于一次上下文切换。
当线程池中的核心线程数量过少时,如果统一时间有大量任务需要处理,可能会导致大量任务在任务队列中排队等待执行,甚至会出现队列满了之后任务无法执行的情况,或者大量任务堆积在任务队列导致内存溢出(OOM)。
课间休息,又来秀一下来自咱们群里同学的搬砖工地,坐标:广州 珠江新城。
===============================================================================
线程池的5种状态:Running
、ShutDown
、Stop
、Tidying
、Terminated
。
-
RUNNING
:线程池的初始化状态是RUNNING
,能够接收新任务,以及对已添加的任务进行处理。 -
SHUTDOWN
:线程池处在SHUTDOWN状态时,不接收新任务
,但能处理已添加的任务。调用线程池的shutdown()接口
时,线程池由RUNNING -> SHUTDOWN
。 -
STOP
:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。 调用线程池的shutdownNow()
接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。 -
TIDYING
:当所有的任务已终止,ctl记录的”任务数量”为0
,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。 -
TERMINATED
:线程池彻底终止,就变成TERMINATED状态
。线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。 当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享