可扩展的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 ...
随机推荐
- MySQL数据库之MyISAM与InnoDB的区别
MySQL数据库之MyISAM与InnoDB的区别 从以下几个方面: 1.存储结构 每个MyISAM在磁盘上存储成三个文件.第一个文件的名字以表的名字开始,扩展名指出文件类型. .frm文件存储表定义 ...
- Centos 7环境下修改主机名
步骤如下: 一.首先把虚拟机打开,用root账户进行登录后打开终端 二.我们看到我们虚拟机名称是默认的主机名. 三.用vi编辑器编辑etc目录下的hostname文件,输入“vi /etc/hostn ...
- Leetcode算法【114. 二叉树展开为链表】
上周通过一位小伙伴,加入了一个氛围很好的小群,人不多,但是大家保持着对知识的渴望,让我很感动. 我自己也有一个群,人数也不多,但是能真正互动起来一起学习,一起进步的,还是太少.所以,现在也在学习如何让 ...
- Extjs导入Excel文件之后grid自动刷新显示刚插入的数据
var winUpload = new Ext.Window({ title: '导入excel文件', width: 400, height:200, listeners: { close: fun ...
- [Part 3] 在Ubuntu 16.04源码编译PCL 1.8.1支持VTK和QT
本文首发于个人博客https://kezunlin.me/post/137aa5fc/,欢迎阅读! Part-3: Install and Configure PCL 1.8.1 with vtk q ...
- SpringMvc demo示例及源码详细分析
三层架构介绍 我们的开发架构一般都是基于两种形式,一种C/S架构,也就是客户端/服务器,另一种是B/S架构,也就是浏览器/服务器.在JavaEE开发中,几乎全部都是基于B/S架构的开发.那么在B/S架 ...
- 复习-java集合简记
1.集合概述 ava集合类存放于 java.util 包中,是一个用来存放对象的容器. 集合只能保存对象(实际上也是保存对象的引用变量),Java主要由两个接口派生而出:Collection和Map, ...
- cenos7搭建gitlab
git.github和gitlab的区别 git:是一种版本控制系统,是一个命令,是一种工具 gitlib:是基于实现功能的开发库 github:是一个基于git实现的在线代码仓库软件 gitlib可 ...
- JavaScript如何创建一个对象
我们可以利用JavaScript的语法特征,以类的思想来创建对象. 方法一:原始方法代码如下: <script> var obj = new Object(); obj.name = &q ...
- VMware中windows虚拟机的安装流程
1.打开安装的VMware 15,点击新建虚拟机 2.选择典型即可,点击下一步 3.选择“稍后安装操作系统”,点击下一步 4.选择想安的版本,点击下一步 ...
