Java之线程池
2022-07-04 14:38:00 30 举报
AI智能生成
Java线程池是一种管理线程的机制,它可以在需要时创建新的线程,并在不需要时回收和重用这些线程。线程池的主要目的是提高系统性能,因为创建和销毁线程都需要消耗系统资源。通过使用线程池,我们可以减少线程创建和销毁的次数,从而降低系统开销。 Java提供了两种类型的线程池:固定大小的线程池和可缓存的线程池。固定大小的线程池包含一定数量的线程,当有任务提交时,如果线程池中有空闲线程,则直接执行任务;如果没有空闲线程,则将任务放入队列等待。可缓存的线程池可以根据需要创建新线程,但如果当前线程数超过最大值,则会回收空闲线程。
作者其他创作
大纲/内容
通过重复利用已创建的线程降低线程创建和销毁造成的消耗
降低资源消耗
当任务到达时,任务可以不需要等到线程创建就能立即执行
提高响应速度
进行统一分配、调优和监控
提高线程的可管理性
好处
默认线程池中没线程,等任务来了才创建线程
如调用了预创建线程prestartAllCoreThreads(),线程池会提前创建并启动所有核心线程
线程池中核心线程的数量
corePoolSize
如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务如果是无界队列则这个参数没有效果
corePoolSize:核心线程数设为5;maxPoolSize:最大线程数设为了10;workQueue队列设为了100; 线程池初始化的时候,线程池中没有线程;
此时来了个任务,线程池就会创建一个线程
如果后面又来了个任务,(无论线程池中是否有闲置的线程,只要,此时线程池中线程数<=5)线程池还会创建一个线程;
按照这样的规则,如果来了5个任务后,线程池中的线程数就达到了5
线程池中的这5个线程,通常会一直存活:即,即使这5个线程都处于空闲状态,其也会一直存在
如果线程池中的5个线程都在执行任务,没有空闲的线程;但是,此时又来了一些任务,其会把任务放在workQueue队列中去,进行排队
如果任务一下来了很多,把队列也排满了;而且,任务继续来的话
那么,线程池会判断,如果此时线程数<10:那么,线程池就会继续创建线程;
如果,队列也满了,线程数也达到了10;如果此时,任务继续来的话,这个任务就会被拒绝
添加线程规则
线程池中允许的最大线程数
maxPoolSize
线程空闲的时间
keepAliveTime的单位
unit
如果线程池当前线程数,多于corePoolSize而且,多余的线程空闲了并且空闲的时间,超过了我们设置的KeepAliveTime那么这些多余的非核心线程,就会被回收
默认为false,若开启为true,则此时线程池中不论核心线程还是非核心线程,只要其空闲时间达到keepAliveTime都会被回收
allowCoreThreadTimeOut
keepAliveTime
用来保存等待执行的任务的阻塞队列
ArrayBlockingQueue
有界队列
最大线程池没用
防止流量突增
OOM异常
LinkedBlockingQueue
PriorityBlockingQueue
无界队列
队列不存线程,所以最大线程数要大
SynchronousQueue
直接交接
使用的阻塞队列
workQueue
用于设置创建线程的工厂
DefaultThreadFactory
threadFactory
RejectedExecutionHandler,线程池的拒绝策略
AbortPolicy :直接抛出异常,默认策略
CallerRunsPolicy :用调用者所在的线程来执行任务
DiscardOldestPolicy :丢弃阻塞队列中靠最前的任务,并执行当前任务
Discard Policy:直接丢弃任务
分类
handler
六大参数
使用单个worker线程的Executor
corePoolSize、maximumPoolSize被设置为1
使用“无界”队列LinkedBlockingQueue作为workerQueue
阻塞队列长度过长,造成oom
分析
newSingleThreadExecutor
可重用固定线程数的线程池
corePoolSize和maximumPoolSize一致
maximumPoolSize、keepAliveTime、RejectedExecutionHandler无效
newFixedThreadPool
会根据需要创建新线程的线程池
corePoolSize=0 maximumPoolSize=Integer.MAX_VALUE
SynchronousQueue作为WorkerQueue
MaximumPoolSize=Integer.MAX_VALUE 创建大量线程造成OOM
如果主线程提交任务的速度高于maximumPool中线程处理任务的速度时,Cached ThreadPool会不断创建新线程,可能会耗尽CPU和内存资源
newCachedThreadPool
延迟周期性的线程池
maximumPoolSize=Integer.MAX_VALUE
DelayedWorkQueue作为WorkerQueue
newScheduledThreadPool
实现用到了ForkJoinPool,用到了分而治之,递归计算的算法
JDK 1.8 newWorkStealingPool
Executors创建线程池
CPU密集型
耗时IO型
情况
线程数 = CPU核心数 *( 1+平均等待时间/平均工作时间 )
计算公式
自定义创建线程池
默认or自定义
shutdown方法是关闭线程池
比如,线程池在执行到一半时,线程中有正在执行的任务,队列中也可能有等待被执行的任务;所以,不是我们调用shutdown方法后,整个线程池就能停的
在我们调用了shutdown方法后,线程池就知道了【我们想要停止线程池的意图】;这个时候,为了安全起见,线程池会把正在执行的任务及队列中等待执行的任务都执行完毕后,再去关闭;
调用了shutdown方法后,如果还有新的任务过来,线程池就会拒绝;
执行完这个方法后,线程池不一定会立即停止
shutdown方法
停止线程池
直接丢弃任务,抛出异常,这是默认策略
AbortPolicy
直接丢弃任务,也不抛出异常
DiscardPolicy
只⽤调⽤者所在的线程来处理任务
CallerRunsPolicy
丢弃等待队列中最旧的任务,并执⾏当前任务
DiscardOldestPolicy
拒绝策略
线程池执行某个任务前会调用
beforeExecute()
任务结束后(任务异常退出)会执行
afterExecute()
线程池执行结束后执行
terminated()
线程池钩子方法
实现的线程复用
运行状态,线程池创建好之后就会进入此状态,如果不手动调用关闭方法,那么线程池在整个程序运行期间都是此状态。
RUNNING
关闭状态,不再接受新任务提交,但是会将已保存在任务队列中的任务处理完。
SHUTDOWN
停止状态,不再接受新任务提交,并且会中断当前正在执行的任务、放弃任务队列中已有的任务。
STOP
整理状态,所有的任务都执行完毕后(也包括任务队列中的任务执行完),当前线程池中的活动线程数降为 0 时的状态。到此状态之后,会调用线程池的 terminated() 方法。
TIDYING
销毁状态,当执行完线程池的 terminated() 方法之后就会变为此状态。
TERMINATED
线程池有哪些状态
避免任务堆积
避免线程数增加
排查线程泄露
线程池的注意点
Java之线程池
0 条评论
回复 删除
下一页