Java 线程池 ThreadPoolExecutor 的那些事儿
线程池基础知识
ThreadPoolExecutor
: 一个线程池
Executors
: 线程池工厂,通过该类可以取得一个拥有特定功能的线程池
ThreadPoolExecutor
类实现了Executor
接口,因此通过这个接口,任何的Runnable
对象都可以被ThreadPoolExecutor
线程池调度。
常见的线程池类型
public static ExecutorService newFixedThreadPool(int nThreads)
返回一个固定线程数量的线程池。线程数量始终不变。当有空闲线程时,立即执行;若没有,新线程暂存在一个任务队列中,待线程空闲,便开始处理任务队列中的任务。
public static ExecutorService newSingleThreadExecutor()
返回一个只有一个线程的线程池。新线程过来存放在任务队列中,线程空闲时,处理任务队列中的任务。
public static ExecutorService newCachedThreadPool()
返回一个可以根据实际情况调整线程数量的线程池。线程的进程数不确定,但是如果有空闲线程可以复用,则会优先使用该线程。如果所有线程都在工作,又有新的任务提交,那么就会创建新的线程执行任务。所有线程在当前任务完成之后,将返回线程池进行服用。
public static ScheduledExecutorService newSingleThreadScheduldExecutor()
返回一个
ScheduledExecutorService
对象,线程池大小为1。在某个固定的延时之后执行,或者周期性执行某个任务public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
和上面一样,但是可以指定线程数。
核心线程池的内部实现
对于核心的几个线程池,其内部实现都是使用了ThreadPoolExecutor
实现。
public static ExecutorService newFixedThreaPool(int nThreads) {
return new ThreadPoolExecutor(nThreads,nThreads,
0L,TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new ThreadPoolExecutor(1,1,
0L,TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,
60L,TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
看一下ThreadPoolExecutor
最重要的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long KeepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
函数的参数含义如下:
corePoolSize
:线程池中的线程数量。maximumPoolSize
:线程池中的最大线程数量。keepAliveTime
:当线程池数量超过corePoolSize
时,多余的空闲线程的存活时间。unit
:keepAliveTime
的单位。workQueue
:任务队列,被提交但是尚未被执行的任务。threadFactory
:线程工厂,用于创建线程,一般用默认的就行。handler
:拒绝策略。当任务太多来不及处理,如何拒绝任务。
在上面的参数中,其他的都好理解,主要是workQueue
和handler
需要重点提及一下。
workQueue
任务队列讲解
workQueue
指被提交但是尚未被执行的任务队列,它是一个BlockingQueue
接口的对象,仅用于存在Runnable
对象。根据队列功能分类,在ThreadPoolExecutor
的构造函数中可以使用以下几种BlockingQueue
:
- 直接提交的队列
SynchronousQueue
:SychronousQueue
是一个特殊的BlockingQueue
。SychronousQueue
没有容量,每一个插入操作都要等待一个相应的删除操作,反之,一个删除操作都要等待对应的插入操作。如果使用SychronousQueue
,提交的任务不会被真实的保存,而总是将新任务提交给线程执行,如果没有空闲线程,那么尝试创建新的线程,如果进程数量已经达到最大值,则执行拒绝策略。因此,使用SychronousQueue
通常要设置很大的maximumcorePoolSize
,否则很容易执行拒绝策略。 - 有界的任务队列
ArrayBlockingQueue
:特点:若有新的任务需要执行,如果线程池的实际线程小于corePoolSize
,则会优先创建新的线程;若大于corePoolSize
,则会将新任务加入到等待队列。如果等待队列已满,无法加入,则在总线成熟不大于maximumPoolSize
的前提下,创建新的线程执行任务。若大于,则执行拒绝策略。 - 无界的任务队列
LinkedBlockingQueue
:特点:若有新的任务需要执行,如果线程池的实际线程小于corePoolSize
,则会优先创建新的线程;若大于corePoolSize
,进入等待队列。 - 优先任务队列
PriorityBlockingQueue
:可以根据任务自身的优先级顺序先后执行。
handler
拒绝策略讲解
JKD
内置的拒绝策略都是通过实现RejectedExecutionHandler
接口实现的,具体如下:
AbortPolicy
策略:直接抛出异常,阻止系统正常工作;CallerRunsPolicy
策略:只要线程未关闭,直接在调用者线程中,运行当前被丢弃的任务。warning:有可能性能会急剧下降DiscardOledstPolicy
策略:丢弃一个最老的请求,并尝试再次提交当前的任务。DiscardPolicy
策略:丢弃无法处理的请求,不予任何处理,不做出任何的提示。
Java 线程池 ThreadPoolExecutor 的那些事儿的更多相关文章
- Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理
相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...
- Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理
相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...
- Java线程池ThreadPoolExecutor使用和分析(一)
相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...
- Java线程池ThreadPoolExecutor类源码分析
前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...
- java线程池ThreadPoolExecutor使用简介
一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...
- Java 线程池(ThreadPoolExecutor)原理分析与使用
在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...
- Java 线程池(ThreadPoolExecutor)原理解析
在我们的开发中“池”的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 有关java线程技术文章还可以推荐阅读:<关于java多线程w ...
- Java线程池(ThreadPoolExecutor)原理分析与使用
在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...
- 转:JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue
从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.ThreadPoolExecutor 就是这样的线程池.以下是我的学习过程. 首先是构 ...
随机推荐
- 华三F100 系列防火墙 - 浮动路由联动NQA 实现双线路自动切换
公司 有两条公网线路,一条移动作为日常主用线路,一条联通作为备用线路. 为了实现主备线路自动切换,配置了浮动路由 但浮动路由只能在 主用接口为down状态时才能浮出接管默认路由.如果故障为非物理链路故 ...
- 【JDK】JDK源码分析-HashMap(1)
概述 HashMap 是 Java 开发中最常用的容器类之一,也是面试的常客.它其实就是前文「数据结构与算法笔记(二)」中「散列表」的实现,处理散列冲突用的是“链表法”,并且在 JDK 1.8 做了优 ...
- 【Spring】No converter found for return value of type: class java.util.ArrayList
错误信息: org.springframework.http.converter.HttpMessageNotWritableException: No converter found for ret ...
- zmnXAglTcg
#include <map>#include <cmath>#include <stack>#include <queue>#include <l ...
- Java基础之二十 并发
20.1 并发得多面性 并发编程令人困惑的一个主要原因:使用并发时需要解决的问题有多个,而实现并发的方法也有多种,并且在这两者之间没有明显的映射关系. 20.1.1 更快的执行 速度问题初听起来很简单 ...
- 激活函数、正向传播、反向传播及softmax分类器,一篇就够了!
1. 深度学习有哪些应用 图像:图像识别.物体识别.图片美化.图片修复.目标检测. 自然语言处理:机器创作.个性化推荐.文本分类.翻译.自动纠错.情感分析. 数值预测.量化交易 2. 什么是神经网络 ...
- vue-cli3.0创建项目报npm install --loglevel error 踩坑的那把辛酸泪
创建项目 vue create vue-pro 然后如下图 一开始以为是npm的问题,卸载了Mac的node ,安装nvm,然后再安装node (可参考: Mac中nvm的安装和使用 https: ...
- js 数组对象深拷贝
js 数组对象深拷贝 结论:对象的拷贝不能采用直接赋值的方式. 背景 踩过的坑如下: formData本来是父组件传过来的,但是我不想直接用,于是我直接赋值给一个formDataCopy的对象. 但是 ...
- 【win】【qt5安装】【qt5.5.1安装及第一个示例make错误】
[前言] 昨天按照需求将qt程序从linux系统移植到win上使用(其实有点缪论了,本人linux用的中标麒麟系统对于发布发布系统版本麒麟(注:以下用麒麟代替中标麒麟,什么银河麒麟,优麒麟的,我现在只 ...
- -bash: redis: command not found
在linux中安装redis,先是拉过去安装,然后通过命令:make 进行编译 编译完成以后通过命令 make install 完成安装:结果在进行启动linux的时候执行 ...