可扩展的Java线程池执行器

抽丝剥茧,细说架构那些事——【优锐课】

Java线程池执行程序偏向于排队而不是产生新线程。从好的方面来说,我们有两种解决方法。

本文来自国内专业IT教育学院【优锐课】。Java学习资料交流qq群:907135806,在接下来的学习如果过程中有任何疑问,欢迎进群探讨。

理想情况下,对任何线程池执行程序而言,期望如下:
• 预先创建了一组初始线程(核心线程池大小)来处理负载。
• 如果负载增加,则应创建更多线程来处理最大线程数(最大池大小)的负载。
• 如果线程数增加到“最大池大小”以外,则将任务排队。
• 如果使用了有界队列,并且队列已满,请引入一些拒绝策略。

下图描述了该过程;仅创建初始线程来处理任务(负载很低时)。
在这里插入图片描述
随着更多的任务进入,假设创建的线程总数小于最大池大小,则会创建更多的线程来处理负载(任务队列仍然为空)。
在这里插入图片描述
如果任务总数大于线程总数(初始+扩展),则任务队列开始填充:
在这里插入图片描述
不幸的是,Java线程池执行器(TPE)偏向于排队而不是生成新线程,即,在初始核心线程被占用之后,任务被添加到队列中,并且在队列达到其限制之后(这只会在有界队列中发生) ),则会产生额外的线程。如果队列不受限制,则完全不会产生扩展线程,如下图所示。
在这里插入图片描述

  1. 创建了初始核心线程来处理负载。
  2. 一旦任务数量超过核心线程数,队列就会开始填满以存储任务。
  3. 队列填满后,将创建扩展线程。
    这是TPE中的代码,出现了问题
    在这里插入图片描述
    我们有两种解决方法:

解决方法1:调整池大小

将corePoolSize 和maximumPoolSize设置为相同的值,并将allowCoreThreadTimeOut 设置为true。

优点

• 无需编码技巧。

缺点

• 由于线程的创建和终止非常频繁,因此没有真正的线程缓存。
• 没有适当的可伸缩性。

解决方法2:覆盖要约方法

• 重写委托人TransferQueue的offer方法,并尝试将任务提供给空闲的工作线程之一。如果没有等待线程,则返回false。
• 实现自定义RejectedExecutionHandler以始终添加到队列中。
在这里插入图片描述
实现自定义RejectedExecutionHandler以始终添加到位数中。

优点

• TransferQueue确保不需要创建线程,并将工作直接转移到等待队列。

缺点

• 不能使用定制的拒绝处理程序,因为它用于插入要排队的任务。

解决方法#3:使用自定义队列

使用自定义队列(TransferQueue)并覆盖offer方法以执行以下操作:

  1. 尝试将任务直接转移到等待队列(如果有)。
  2. 如果以上操作失败,并且未达到最大池大小,则通过从offer方法返回false来创建扩展线程。
  3. 否则,将其插入队列。
    在这里插入图片描述

优点

• TransferQueue确保不需要创建线程,并将工作直接转移到等待队列。
• 可以使用自定义拒绝处理程序。

缺点

• 队列和执行程序之间存在循环依赖关系。

解决方法4:使用自定义线程池执行程序

使用专门用于此目的的自定义线程池执行程序。它使用系统@ Facebook规模中所述的LIFO调度。

————————————————————————————————————
本文来自国内专业IT教育学院【优锐课】

Java学习资料交流qq群:907135806,在接下来的学习如果过程中有任何疑问,欢迎进群探讨。

也可以添加vx:ddmsiqi,有更多JVM、Mysql、Tomcat、Spring Boot、Spring Cloud、Zookeeper、Kafka、RabbitMQ、RockerMQ、Redis、ELK、Git等Java学习资料和视频课程!在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值