Executors、ThreadPoolExecutor线程池讲解
官方+白话讲解Executors、ThreadPoolExecutor线程池使用
Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是ThreadPoolExecutor,使用默认线程池配置参数。
建议:对于大用户,高并发,不易掌控的项目,不建议使用Executors来创建线程池对象。
对于易于掌控且并发数不高的项目,可以考虑Executors。
ThreadPoolExecutor:线程池对象,实现ExecutorService接口,可以自定义线程池核心线程数、最大线程数、空闲时间、缓冲队列等。
建议:大用户,高并发,不易于掌控的项目,建议根据物理服务器配置,任务需求耗时,可能存在的并发量,自定义配置ThreadPoolExecutor线程信息。
一般项目会封装ThreadPoolExecutor工具类,因为需要考虑新手有时会乱用,也方便于统一灵活管理。
一、先说下Executors 创建线程池的三种策略
1.创建无边界缓存线程池:Executors.newCachedThreadPool()
无边界缓存界线程池:不限制最大线程数的线程池,且线程有空闲存活时长。
接着看下JDK Executors.newCachedThreadPool()源码:
源码可以可以看到,该方法创建了一个线程池为:核心线程数0,最大线程数Integer.MAX_VALUE(可以理解为无上限),线程空闲存活时长60,单位TimeUnit.SECONDS秒,缓冲队列是SynchronousQueue的线程池。
因为最大线程数没有上限,所以,大用户,高并发项目使用时一定要严谨配置。
关于SynchronousQueue缓冲队列的缓冲数是1,不过每次都被线程池创建取走,所以该缓冲对联永远isEmpty=true。具体细节先百度,后续有时间我再讲解。
2.创建有边界线程池:Executors.newFixedThreadPool(200)
有边界线程池:有最大线程数限制的线程池。
接着看下JDK Executors.newFixedThreadPool(200)源码:
源码可以可以看到,该方法创建了一个线程池为:核心线程数nThreads(200),最大线程数nThreads (200),线程空闲存活时长0,单位TimeUnit.SECONDS秒,缓冲队列是LinkedBlockingQueue的线程池。
LinkedBlockingQueue这里没有定义长度,也就是说这个缓冲队列的容量没有上限,大用户,高并发项目使用时一定要严谨配置。
3.创建单线程线程池:Executors.newSingleThreadExecutor()
单线程线程池:线程池里只有一个线程数,其他都存在缓冲队列里,
接着看下JDK Executors.newSingleThreadExecutor()源码:
源码可以可以看到,该方法创建了一个线程池为:核心线程数1,最大线程数1,线程空闲存活时长0,单位TimeUnit.MILLISECONDS毫秒,缓冲队列是LinkedBlockingQueue的线程池。
LinkedBlockingQueue这里没有定义长度,也就是说这个缓冲队列的容量没有上限,大用户,高并发项目使用时一定要严谨配置。
使用场景:任务需要逐一调度执行。
二、ThreadPoolExecutor自定义配置线程池对象
通过上面的Executors,我们对创建线程池已经有了点了解。
下面直接看构造函数的源码,我把参数解释为白话文
/**
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
核心线程数,核心线程数永远小于等于最大线程数。
缓冲队列不满时,线程池的线程数用远小于等于核心线程数。
缓冲队列满时,线程池会在核心线程数的基础上再创建线程,但小于最大线程数
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
线程池最大线程数
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
线程空闲存活时长
* @param unit the time unit for the {@code keepAliveTime} argument
线程存活时长单位
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
缓冲队列,BlockingQueue接口的实现类,根据需求选择他的实现类即可,细节有必要去找度娘。
常用BlockingQueue有LinkedBlockingQueue和SynchronousQueue
* @param threadFactory the factory to use when the executor
* creates a new thread
线程工厂,用来创建线程的,使用默认的就好
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
缓冲队列已满且已经最大线程数,这时的处理策略
RejectedExecutionHandler下有多个实现类,根据所需决定
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
在开发实战中,对于多线程颇为了解的,我建议根据硬件和软件需求结合,自定义创建ThreadPoolExecutor线程池。
Executors、ThreadPoolExecutor线程池讲解的更多相关文章
- ThreadPoolExecutor 线程池的源码解析
1.背景介绍 上一篇从整体上介绍了Executor接口,从上一篇我们知道了Executor框架的最顶层实现是ThreadPoolExecutor类,Executors工厂类中提供的newSchedul ...
- j.u.c系列(01) ---初探ThreadPoolExecutor线程池
写在前面 之前探索tomcat7启动的过程中,使用了线程池(ThreadPoolExecutor)的技术 public void createExecutor() { internalExecutor ...
- 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!
作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...
- 源码剖析ThreadPoolExecutor线程池及阻塞队列
本文章对ThreadPoolExecutor线程池的底层源码进行分析,线程池如何起到了线程复用.又是如何进行维护我们的线程任务的呢?我们直接进入正题: 首先我们看一下ThreadPoolExecuto ...
- 手写一个线程池,带你学习ThreadPoolExecutor线程池实现原理
摘要:从手写线程池开始,逐步的分析这些代码在Java的线程池中是如何实现的. 本文分享自华为云社区<手写线程池,对照学习ThreadPoolExecutor线程池实现原理!>,作者:小傅哥 ...
- ThreadPoolExecutor 线程池的实现
ThreadPoolExecutor继承自 AbstractExecutorService.AbstractExecutorService实现了 ExecutorService 接口. 顾名思义,线程 ...
- 13.ThreadPoolExecutor线程池之submit方法
jdk1.7.0_79 在上一篇<ThreadPoolExecutor线程池原理及其execute方法>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法 ...
- javade多任务处理之Executors框架(线程池)实现的内置几种方式与两种基本自定义方式
一 Executors框架(线程池) 主要是解决开发人员进行线程的有效控制,原理可以看jdk源码,主要是由java.uitl.concurrent.ThreadPoolExecutor类实现的,这里只 ...
- Java并发——ThreadPoolExecutor线程池解析及Executor创建线程常见四种方式
前言: 在刚学Java并发的时候基本上第一个demo都会写new Thread来创建线程.但是随着学的深入之后发现基本上都是使用线程池来直接获取线程.那么为什么会有这样的情况发生呢? new Thre ...
随机推荐
- typora的使用技巧
目录 Typora 的 markdown 语法 标题: 插入图片: 链接: 字体变化: 删除: 文字高亮: 角标: 文本方位: :-:| :- | -: 制作表格: 常用快捷键(补充): 下划线: T ...
- virtualbox安装问题总结
还是老问题 重点重点: https://blog.csdn.net/Loisleen/article/details/84975165#1install_the_gcc_make_perl_packa ...
- filbeat遇到的坑(运行久和文件数据量多时候 )
1.现像,吃cpu,&& io 过程:量大的时候发现在filbeat很吃io, 原因: 日志量文件数太多,因为日志是2m一个文件 ,一天几十个G 开始怀疑是centos 6的问题,, ...
- 计算机原理学习(1)-- 冯诺依曼体系和CPU工作原理
前言 对于我们80后来说,最早接触计算机应该是在95年左右,那个时候最流行的一个词语是多媒体. 依旧记得当时在同学家看同学输入几个DOS命令就成功的打开了一个游戏,当时实在是佩服的五体投地.因为对我来 ...
- 使用PhantomJS后台web界面截图
自动化截web页面的图 一.工具介绍: PhantomJS是一个基于webkit的JavaScript API.它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JavaSc ...
- prometheus自定义监控指标——实战
上一节介绍了pushgateway的作用.优劣以及部署使用,本机通过几个实例来重温一下自定义监控指标是如何使用的. 一.监控容器启动时间(shell) 使用prometheus已经两个月了,但从未找到 ...
- python虚拟环境切换无效问题
使用pycharm创建新项目,使用虚拟环境,但是进入到项目的cainiao_guoguo_health\venv\Scripts目录启动虚拟环境后,安装第三方库,却还是安装到其他环境中去了, 检查ac ...
- linux阿里云服务器更换镜像的方法
linux阿里云服务器更换镜像的方法 1 先进入硬盘创建快照 生成自定义镜像 ps:他可以在阿里云各个服务器上共享 再左侧镜像 点击去可以看到共享 直接进ecs 关闭服务器 重新初始化硬盘 然后主界面 ...
- Rancher 构建 CI/CD 自动化流程 - 动态配置 Jenkins-slave(二)
一.说明 1.1 说明 前面介绍采用 Jenkinsfile + KubernetesPod.yaml 方式进行部署项目(Rancher 构建 CI/CD 自动化流程 - 动态配置 Jenkins-s ...
- Lambda表达式和方法引用
1 , 为什么用lambda表达式 将重复固定的代码写法简单化 2 ,lambda表达式的实质 对函数式接口的实现(一个接口中只有一个抽象方法的接口被称为函数式接口) package com.mo ...