ThreadPoolExecutor 介绍
线程池能够带来3个好处:
降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗;
提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行;
提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
超过可容纳任务数后,按策略处理
可容纳任务数 = 最大线程数(maximumPoolSize)+ 最大队列数(workQueue.size())
线程资源必须通过线程池提供, 不允许在应用中自行显式创建线程。
说明: 线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销, 解决资源不足的问题。如果不使用线程池, 有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换” 的问题。
线程池不允许使用 Executors 去创建, 而是通过 ThreadPoolExecutor 的方式, 这样的处理方式让写的同学更加明确线程池的运行规则, 规避资源耗尽的风险。
说明: Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE, 可能会堆积大量的请求, 从而导致 OOM。
2) CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE, 可能会创建大量的线程, 从而导致 OOM。
3) ScheduledThreadPool:允许的请求队列长度为 Integer.MAX_VALUE, 可能会堆积大量的请求, 从而导致 OOM。
CPU核数:可以通过 Runtime.getRuntime().availableProcessors() 获得
/**
*
* @param corePoolSize 核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。CPU核数+1
* @param maximumPoolSize 线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。 CPU核数*2+1
* @param keepAliveTime 非核心线程的闲置超时时间,超过这个时间就会被回收。
* @param unit 指定keepAliveTime的单位,如TimeUnit.SECONDS。当将allowCoreThreadTimeOut设置为true时对corePoolSize生效。
* @param workQueue 线程池中的任务队列.常用的有三种队列
* a.SynchronousQueue:是一种无缓冲的等待队列,在某次添加元素后必须等待其他线程取走后才能继续添加;
* b.LinkedBlockingDeque:是一个无界缓存的等待队列,不指定容量则为Integer最大值,锁是分离的;
* c.ArrayBlockingQueue:是一个有界缓存的等待队列,必须指定大小,锁是没有分离的;
* @param threadFactory 线程工厂,提供创建新线程的功能,通过线程工厂可以对线程的一些属性进行定制。
* @param handler 当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution方法,线程池有以下四种拒绝策略。
* a.AbortPolicy:当任务添加到线程池中被拒绝时,它将抛出RejectedExecutionException 异常。会有日志出来。正常可以用这个
* b.CallerRunsPolicy:当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中run被拒绝的任务。 运行出来的进程名是 main
* c.DiscardOldestPolicy:当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务(丢弃队列最前面的任务),然后将被拒绝的任务添加到等待队列中。
* d.DiscardPolicy:当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。没有日志输出,系统统无感
*/
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {}
线程池状态含义:
RUNNING:接受新任务并且处理阻塞队列里的任务;
SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务;
STOP:拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务;
TIDYING:所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为 0,将要调用 terminated 方法
TERMINATED:终止状态。terminated 方法调用完成以后的状态;
线程池状态转换:
RUNNING -> SHUTDOWN:显式调用 shutdown() 方法,或者隐式调用了 finalize(),它里面调用了shutdown()方法。
RUNNING or SHUTDOWN)-> STOP:显式 shutdownNow() 方法;
SHUTDOWN -> TIDYING:当线程池和任务队列都为空的时候;
STOP -> TIDYING:当线程池为空的时候;
TIDYING -> TERMINATED:当 terminated() hook 方法执行完成时候;
线程池的监控:
通过线程池提供的参数进行监控。线程池里有一些属性在监控线程池的时候可以使用
getTaskCount:线程池已经执行的和未执行的任务总数;
getCompletedTaskCount:线程池已完成的任务数量,该值小于等于 taskCount;
getLargestPoolSize:线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过,也就是达到了maximumPoolSize;
getPoolSize:线程池当前的线程数量;
getActiveCount:当前线程池中正在执行任务的线程数量。
做几个计算
corePoolSize = 每秒需要多少个线程处理?
threadcount = tasks/(1/taskcost) =tasks*taskcout = (100~1000)*0.1 = 10~100 个线程。corePoolSize设置应该大于10根据8020原则,如果80%的每秒任务数小于200,那么corePoolSize设置为20即可
queueCapacity = (coreSizePool/taskcost)*responsetime 计算可得 queueCapacity = 20/0.1*1 = 200。意思是队列里的线程可以等待1s,超过了的需要新开线程来执行切记不能设置为Integer.MAX_VALUE,这样队列会很大,线程数只会保持在corePoolSize大小,当任务陡增时,不能新开线程来执行,响应时间会随之陡增。
maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost) 计算可得 maxPoolSize = (1000-200)/10 = 80(最大任务数-队列容量)/每个线程每秒处理能力 = 最大线程数
rejectedExecutionHandler:根据具体情况来决定,任务不重要可丢弃,任务重要则要利用一些缓冲机制来处理
keepAliveTime和allowCoreThreadTimeout采用默认通常能满足
以上关于线程数量的计算并没有考虑CPU的情况。若结合CPU的情况,比如,当线程数量达到60时,CPU达到100%,则将maxPoolSize设置为80也不合适,此时若系统负载长时间维持在每秒1000个任务,则超出线程池处理能力,应设法降低每个任务的处理时间(taskcost)。
ThreadPoolExecutor 介绍的更多相关文章
- (转)java中Executor、ExecutorService、ThreadPoolExecutor介绍
转自: http://blog.csdn.net/linghu_java/article/details/17123057 ScheduledThreadPoolExecutor介绍: http:// ...
- ThreadPoolExecutor介绍
ThreadPoolExecutor的说明 ThreadPoolExecutor常见的操作主要有以下几个方法: getPoolSize():返回线程池实际的线程数. getActiveCount(): ...
- java线程池技术(二): 核心ThreadPoolExecutor介绍
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...
- java中Executor、ExecutorService、ThreadPoolExecutor介绍(转)
1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /** * Executes th ...
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /** * Executes the given c ...
- ThreadPoolExecutor解析
前言:在最新的阿里规范中强制使用ThreadPoolExecutor方式创建线程池,不允许使用Executors,因此有必要对ThreadPoolExecutor进行进一步了解. 1.ThreadPo ...
- Java并发编程总结5——ThreadPoolExecutor
一.ThreadPoolExecutor介绍 在jdk1.8中,构造函数有4个.以 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, ...
- ThreadPoolExecutor线程池解析与BlockingQueue的三种实现
目的 主要介绍ThreadPoolExecutor的用法,和较浅显的认识,场景的使用方案等等,比较忙碌,如果有错误还请大家指出 ThreadPoolExecutor介绍 ThreadPoolExecu ...
- 多线程编程学习十一(ThreadPoolExecutor 详解).
一.ThreadPoolExecutor 参数说明 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keep ...
- Android的线程和线程池
---恢复内容开始--- 一.Android线程的形态 (一)AsyncTask解析 AysncTask简介:①.实现上封装了Thread和Handler ②.不适合进行特别耗时的后台任务 Ays ...
随机推荐
- 编写高性能C#代码 —— Span<T>
Span 提供任意内存的连续区域的类型安全和内存安全表示形式.它是在堆栈而不是托管堆上分配的ref结构,是对任意内存块的抽象 . 1.关于Span 在NET Core 2.1中首次引入 提供对任意内存 ...
- AcWing 168. 生日蛋糕
原题链接:AcWing 168. 生日蛋糕 设当前体积是\(v,h.r\)分别记录每层的高度和半径,由于整个蛋糕的上表面面积等于最大蛋糕的圆面积,所以枚举到最大一层的时候直接加上即可. 优化搜索顺序: ...
- css零散笔记——修改input样式input:-internal-autofill-selected背景色
闲聊: 小颖项目中的登录页需将 input 背景色设为透明,小颖将 input 的背景色设置后,发现表单自动填充后还是会有背景色,然后发现 浏览器 自带了背景色: 效果图: ...
- 【Android】无法通过drawable下的selector类型改变背景颜色?
举例 我在darwable目录下创建了selector文件,并设置了如下内容 <?xml version="1.0" encoding="utf-8"?& ...
- 【JSOI2008】火星人 (哈希+Splay)
题目 这种含有修改操作的就难以用后缀数组实现了,求LCP这种区间相等的类型可以想到用hash判断,同时LCP的答案大小符合二分条件可以二分求出,如果只有修改可以用线段树维护,因为还有有插入操作所以想到 ...
- 从0开始用Maven
一.Maven的介绍即相关概念 Maven是一款构建和管理Java项目的工具,它将项目开发和管理过程抽象成一个项目对象模型(POM),提供了一种统一的项目结构. Maven官网 1.为什么使用Mave ...
- [ABC262B] Triangle (Easier)
Problem Statement You are given a simple undirected graph with $N$ vertices and $M$ edges. The verti ...
- 使用create-vue创建vue3项目
create-vue是vue3新的脚手架搭建项目工具,底层构建工具使用vite,而不是vue-cli的webpack. 但不是说你不能用以前的vue create命令来创建vue3项目,你完全可以用v ...
- Scrapy集成selenium-案例-淘宝首页推荐商品获取
scrapy特性就是效率高,异步,如果非要集成selenium实际上意义不是特别大....因为selenium慢.... 案例:淘宝首页推荐商品的标题获取 爬虫类 toabao.py import s ...
- Scrapy框架架构
ENGINE:引擎,负责各个组件的管理. SPIDERS:各个爬虫文件类.(我们一般要写的代码就是这个). SCHEDULER:调度器,ENGINE将爬虫任务分发给该组件,由该组件调度爬虫任务. DO ...