十分详细讲述的ThreadPoolExecutor线程池

1、线程池状态

ThreadPoolExecutor使用int的高3位来表示线程池状态,低29位表示线程数量,即使用一个整数的不同位来表示

这些信息存储在一个原子变量ctl中,目的是将线程池状态与线程的个数合二为一,这样就可以用一次cas原子操作进行赋值

2、构造方法

最大线程数目 = 核心线程数 + 救急线程数

  • 线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。
  • 当线程数达到corePoolSize并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue队列中排队,直到有空闲的线程。
  • 如果有队列选择了有界队列,那么任务超过了队列大小时,会创建maximumPoolSize(最大线程数) - corePoolSize(核心线程数) 数目的线程来救急
  • 如果线程到达了maximumPoolSize仍然有新任务这时会执行拒绝策略。拒绝策略jdk提供了4种实现,其他著名的框架也提供了实现
    • AbortPolicy 让调用者抛出RejectedExecutionException,这是默认策略
    • CallerRunPolicy 让调用者运行任务
    • DiscardPolicy 放弃本次任务
    • DiscardOldsetPolicy 放弃队列中最早的任务,本任务取而代之
    • Dubbo 的问题实现,在抛出RejectedExecutionException异常之前会记录日志,并dump线程栈信息,方便定位问题
    • Netty的实现,创建一个新线程来执行任务
    • ActiveMQ的实现,带超时等待(60s)尝试放入队列
    • PinPoint的实现,他使用了一个拒绝策略链,会逐一尝试策略链中每种拒绝策略
  • 当高峰过去后,超过核心线程数的救急线程如果一段时间没有任务做,需要结束节省资源,这个时间由keepAliveTime和unit来控制。

根据这个构造方法,JDK Executors 类中提供了众多工厂方法来创建各自用途的线程池

3、newFixedThreadPool(

  • 核心线程数 == 最大线程数(没有救急线程被创建) ,因此也无需超时时间
  • 阻塞队列是无界的,可以放任意数量的任务

适用于任务量已知,且相对耗时的任务

 4、newCachedThreadPool

  • 核心线程数是0,最大线程数是Integer.MAX_VALUE,救急线程的空闲生存时间是60s,意味着
    • 每个线程都是救急线程(60s后可以被回收) 
    • 救急线程可以无限被创建
  • 队列采用了SynchronousQueue,其特点是,它没有容量,没有线程来取是放不进去的(一手交钱,一手交货)
    • SynchronousQueue可以说是为了这个newCachedThreadPool而生的,只要有任务,我就会创建新的救急线程,然后来处理这个任务

整个线程池表现为线程数会根据任务量不断增长,没有上限,当任务执行完毕,空闲1分钟后释放线程。

适合任务数比较密集,但每个任务执行时间较短的情况

5、newSingleThreadExecutor

 使用场景

希望多个任务排队执行。线程数固定为1,任务数多于1时,会放入无界队列排队。任务执行完毕,这唯一的线程也不会被释放

6、让线程池执行任务 

7、关闭线程池 

void shutdown();

  • 不会接收新任务
  • 但已提交任务会执行完
  • 此方法不会阻塞调用线程的执行

最后不会等的意思是,不会去等待运行中的线程执行完毕,同样也不会去终止,就让他自己执行完自己销毁就行了

List<Runnable> shutdownNow();

  •  不会接收新任务
  • 会将队列中的任务返回
  • 并用interrupt的方式中断正在执行的任务

关于关闭线程池的其他方法

Tomcat线程池

  •  LimitLatch 用来限流,可以控制最大链接个数
  • Acceptor只负责【接收新的socket连接】
  • Poller只负责监听socket channel是否有【可读的I/O时间】
  • 一旦可读,封装一个任务对象(sockerProcessor),提交给Executor线程池处理
  • Executor线程池中的工作线程最终负责【处理请求】

Tomcat线程池拓展了ThreadPoolExecutor,行为稍有不同

  • 如果总线程数达到maximumPoolSize
    • 这时不会立即抛RejectedExecutionException异常
    • 而是再次尝试将任务放入队列,如果还失败,才抛出RejectedExecutionException异常

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadPoolExecutorJava中的一个线程池实现类。它继承自ExecutorService接口,可以用来管理和执行线程任务。ThreadPoolExecutor线程池提供了更灵活的线程管理和任务调度的功能,并且可以根据需要进行配置。可以通过指定核心线程数、最大线程数、线程存活时间和任务队列等参数来创建和配置ThreadPoolExecutor线程池。 使用ThreadPoolExecutor线程池可以提供以下几个优点: 1. 降低线程创建和销毁的开销。线程池可以重用已经创建的线程,减少了频繁创建和销毁线程的开销。 2. 提高系统的响应速度。线程池可以并发执行多个任务,提高了系统的处理能力和响应速度。 3. 控制线程并发数量。通过设置线程池的核心线程数和最大线程数,可以控制系统的并发线程数量,避免资源耗尽和系统崩溃的风险。 4. 提供任务调度和管理。线程池可以将任务按照一定的策略和优先级进行调度和执行,方便管理任务的执行顺序和优先级。 总之,ThreadPoolExecutor线程池是一个灵活可配置的线程管理和任务调度工具,可以提高系统的并发处理能力和响应速度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [线程池ThreadPoolExecutor详解(整理详细)](https://blog.csdn.net/trusause/article/details/125747447)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [ThreadPoolExecutor线程池的使用方法](https://download.csdn.net/download/weixin_38659648/12746355)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值