可扩展的Java线程池执行器
分享一下最近优锐课学习笔记。
Java线程池执行程序偏向于排队而不是产生新线程。从好的方面来说,我们有两种解决方法。
理想情况下,对任何线程池执行程序而言,期望如下:
- 预先创建了一组初始线程(核心线程池大小)来处理负载。
- 如果负载增加,则应创建更多线程来处理最大线程数(最大池大小)的负载。
- 如果线程数增加到“最大池大小”以外,则将任务排队。
- 如果使用了有界队列,并且队列已满,请引入一些拒绝策略。
下图描述了该过程;仅创建初始线程来处理任务(负载很低时)。

随着更多的任务进入,假设创建的线程总数小于最大池大小,则会创建更多的线程来处理负载(任务队列仍然为空)。

如果任务总数大于线程总数(初始+扩展),则任务队列开始填充:
不幸的是,Java线程池执行器(TPE)偏向于排队而不是生成新线程,即,在初始核心线程被占用之后,任务被添加到队列中,并且在队列达到其限制之后(这只会在有界队列中发生) ),则会产生额外的线程。如果队列不受限制,则完全不会产生扩展线程,如下图所示。

- 创建了初始核心线程来处理负载。
- 一旦任务数量超过核心线程数,队列就会开始填满以存储任务。
- 队列填满后,将创建扩展线程。
这是TPE中的代码,出现了问题

我们有两种解决方法:
解决方法1:调整池大小
将corePoolSize 和maximumPoolSize设置为相同的值,并将allowCoreThreadTimeOut 设置为true。
优点
- 无需编码技巧。
缺点
- 由于线程的创建和终止非常频繁,因此没有真正的线程缓存。
- 没有适当的可伸缩性。
解决方法2:覆盖要约方法
- 重写委托人TransferQueue的offer方法,并尝试将任务提供给空闲的工作线程之一。如果没有等待线程,则返回false。
- 实现自定义RejectedExecutionHandler以始终添加到队列中。
实现自定义RejectedExecutionHandler以始终添加到位数中。
优点
- TransferQueue确保不需要创建线程,并将工作直接转移到等待队列。
缺点
- 不能使用定制的拒绝处理程序,因为它用于插入要排队的任务。
解决方法#3:使用自定义队列
使用自定义队列(TransferQueue)并覆盖offer方法以执行以下操作:
- 尝试将任务直接转移到等待队列(如果有)。
- 如果以上操作失败,并且未达到最大池大小,则通过从offer方法返回false来创建扩展线程。
- 否则,将其插入队列。

优点
- TransferQueue确保不需要创建线程,并将工作直接转移到等待队列。
- 可以使用自定义拒绝处理程序。
缺点
- 队列和执行程序之间存在循环依赖关系。
解决方法4:使用自定义线程池执行程序
使用专门用于此目的的自定义线程池执行程序。它使用系统@ Facebook规模中所述的LIFO调度。
可扩展的Java线程池执行器的更多相关文章
- Netty核心概念(7)之Java线程池
1.前言 本章本来要讲解Netty的线程模型的,但是由于其是基于Java线程池设计而封装的,所以我们先详细学习一下Java中的线程池的设计.之前也说过Netty5被放弃的原因之一就是forkjoin结 ...
- Java并发编程系列-(6) Java线程池
6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...
- 【转载】深度解读 java 线程池设计思想及源码实现
总览 开篇来一些废话.下图是 java 线程池几个相关类的继承结构: 先简单说说这个继承结构,Executor 位于最顶层,也是最简单的,就一个 execute(Runnable runnable) ...
- Java并发指南12:深度解读 java 线程池设计思想及源码实现
深度解读 java 线程池设计思想及源码实现 转自 https://javadoop.com/2017/09/05/java-thread-pool/hmsr=toutiao.io&utm_ ...
- Java 线程池框架核心代码分析--转
原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...
- (转载)JAVA线程池管理
平时的开发中线程是个少不了的东西,比如tomcat里的servlet就是线程,没有线程我们如何提供多用户访问呢?不过很多刚开始接触线程的开发攻城师却在这个上面吃了不少苦头.怎么做一套简便的线程开发模式 ...
- Java 线程池框架核心代码分析
前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和资源消耗都是很高的.线程池应运而生,成为我们管理线程的利器.Java 通过Executor接口,提供了一种标准的方法将任务的提交过 ...
- Java线程池使用和分析(一)
线程池是可以控制线程创建.释放,并通过某种策略尝试复用线程去执行任务的一种管理框架,从而实现线程资源与任务之间的一种平衡. 以下分析基于 JDK1.7 以下是本文的目录大纲: 一.线程池架构 二.Th ...
- 由浅入深理解Java线程池及线程池的如何使用
前言 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担.线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致Out of Memory ...
随机推荐
- [Office] Resources for Office Development
Office 2013 Document (.chm) download page: http://www.microsoft.com/en-us/download/details.aspx?id=4 ...
- ThinkPHP v5.1.x POP 链分析
环境:MacOS 10.13 MAMAP Prophp 7.0.33 + xdebugVisual Studio Code前言我所理解的 POP Chain:利用魔术方法并巧妙构造特殊属性调用一系列函 ...
- 力扣(LeetCode)Excel表列序号 个人题解
给定一个Excel表格中的列名称,返回其相应的列序号. 例如, A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ...
- RNN-LSTM讲解-基于tensorflow实现
cnn卷积神经网络在前面已经有所了解了,目前博主也使用它进行了一个图像分类问题,基于kaggle里面的food-101进行的图像识别,识别率有点感人,基于数据集的关系,大致来说还可行.下面我就继续学习 ...
- 程序员需要掌握的七种 Python 代码更易维护的武器
检查你的代码风格 PEP 8 是 Python 代码风格规范,它规定了类似行长度.缩进.多行表达式.变量命名约定等内容.尽管你的团队自身可能也会有稍微不同于 PEP 8 的代码风格规范,但任何代码风格 ...
- python3 之 判断闰年小实例
一.方法1: while True: try: year = int(input('请输入一个年份:')) if (year % 4) == 0 and (year % 100) != 0 or (y ...
- Github远程库与Git本地库连接
Github远程库与Git本地库连接 以下有任何[]符号只是将内容扩起,输入命令不需要将[]加入 创建SSH Key 用户主目录有.ssh->id_rsa和id_rae.pub->直接跳过 ...
- scrapy自动抓取蛋壳公寓最新房源信息并存入sql数据库
利用scrapy抓取蛋壳公寓上的房源信息,以北京市为例,目标url:https://www.dankegongyu.com/room/bj 思路分析 每次更新最新消息,都是在第一页上显示,因此考虑隔一 ...
- windows和linux的开机顺序
windows的开机顺序: 启动自检阶段---初始化启动阶段---Boot加载阶段---检测和配置硬件阶段---内核加载阶段---屏幕显示. linux的开机启动顺序: 加载Bios---读取MBR- ...
- Django Form and ModelForm
Form介绍 在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输 ...
