vlambda博客
学习文章列表

10分钟了解线程池,阿里再也不担心我线程池资源耗尽了

线程池:避免了创建线程和销毁线程的资源损耗。

Executors提供四种线程池:

  • newCachedThreadPool :缓存线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。

  • newFixedThreadPool :定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  • newScheduledThreadPool :计划线程池,支持定时及周期性任务执行。

  • newSingleThreadExecutor :单线程线程池,用唯一的线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

先了解下线程池必备的以下几个属性:

poolSize : 当前程序运行的线程数。

coreSize:  核心线程数。

MaximumPoolSize: 线程池中最大线程数。

keepAliveTime:线程空闲时间超过,则会超时退出。

BlockingQueue :设置一个阻塞用来存放将要执行的等待任务。

(线程安全:保证取队列元素时一个只能取一个,且头元素没有时不能取,满时不能加入)

线程池的运行流程:

当需要执行一个任务时:

poolsize < coresize ->开启一个新的线程执行

poolsize = coresize && 队列未满  -> 这时已经达到了核心线程数,线程不够了,加入到阻塞队列中,慢慢执行。

Poolsize < MaximumPoolSize && 队列已满  -> 这时队列都满了,那不行啊 ,快爆了,在开启一个新线程吧。

(通常超出核心线程的线程是“借”的,也就是说超出核心线程的情况算是一种能够预见的异常情况,并且这种情况并不常常发生(如果常常发生,那我想你应该调整你的核心线程数了)

Poolsize = MaximumPoolSize  && 队列满了 -> 已经所有办法用尽了,会根据饱和策略RejectedExecutionHandler拒绝新的任务。

(如果设置了keepAliveTime,可以通过以下配置来确定小于corePoolSize时,是否启动超时处理。

但是对于超出MaximumPoolSize,一定会进行超时处理,因为这些线程本就不是正常情况。

allowCoreThreadTimeOut:是否允许核心线程超时退出。

如果该值为false(默认),且poolSize<=corePoolSize,线程池都会保证这些核心线程处于存活状态,不会超时退出。(所以只要不是超过corePoolSize,线程都会空闲而不是销毁)

如果为true,则不论poolSize的大小,都允许超时退出。

如果poolSize>corePoolSize,则该参数不论true还是false,都允许超时退出。

)

下面就看看创建线程的源码:

自定义线程池:

10分钟了解线程池,阿里再也不担心我线程池资源耗尽了

固定大小线程池:

10分钟了解线程池,阿里再也不担心我线程池资源耗尽了

单个线程池

10分钟了解线程池,阿里再也不担心我线程池资源耗尽了

缓存线程池:

10分钟了解线程池,阿里再也不担心我线程池资源耗尽了

定时线程池:

10分钟了解线程池,阿里再也不担心我线程池资源耗尽了

线程池拒绝策略:

当线程池满了,队列也满了,这时候需要执行拒绝策略。默认策略感觉不太好,如果一满就会报异常停止运行。

AbortPolicy(默认)

默认策略,直接跑出异常阻止系统正常运行

CallerRunsPolicy

“调用者运行”一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将任务回馈至调用方,比如main线程

DiscardOldestPolicy

抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

DiscardPolicy

直接丢弃任务,不给予任何处理也不跑出异常,如果允许任务丢失

10分钟了解线程池,阿里再也不担心我线程池资源耗尽了