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 ...
随机推荐
- 持续集成指南:GitHubAction 自动构建+部署AspNetCore项目
前言 之前研究了使用 GitHub Action 自动构建和发布 nuget 包:开发现代化的.NetCore控制台程序:(4)使用GithubAction自动构建以及发布nuget包 现在更进一步, ...
- 1. 手动移植FreeRTOS V9.00到 Stm32F103C8T6
记录移植过程,以便以后查看: 附上FreeRTOS源码和 测试文件: 链接:https://pan.baidu.com/s/1v6nvDOk4-2NILYqN3njGjQ 提取码:1234 1.使用 ...
- The 2021 ICPC Asia Regionals Online Contest (II) L Euler Function
思路来源:Zed222 如果一个区间里的数都有这个质数,那么我们就直接利用性质\(\phi(n * p) = \phi(n) * p\),如果没有这个区间中有没有这个质数的,那么就退化到了单点修改,当 ...
- Android 的异步消息处理机制
前言 Android中的异步消息处理机制主要有四部分:Message.Handler.MessageQuene.Looper.这一消息处理机制也称为Handler机制.Handler机制是支撑整个An ...
- ZooKeeper论文阅读笔记
ZooKeeper论文传送门 介绍 ZooKeeper 是一个开源的分布式协调服务,它提供了高可用性和一致性的数据管理和协调功能.它被设计用于构建可靠的分布式系统,并提供了一组简单而强大的 wait- ...
- SpringBoot接口开发
依赖的jar包<dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- [ABC265D] Iroha and Haiku (New ABC Edition)
Problem Statement There is a sequence $A=(A_0,\ldots,A_{N-1})$ of length $N$. Determine if there exi ...
- spring报错-Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 63
这个错误原因是因为JDK版本过高,改一下版本就行了 把里面的19改成8 这样就行了
- C++学习笔记七:输出格式<ios><iomanip>
这一篇主要总结一下C++标准库里输出格式相关的库函数. https://en.cppreference.com/w/cpp/io/manip 1.库: <ostream> <ios& ...
- Head First Java学习:第十一章-异常处理
第十一章 异常处理 1.方法可以抓住其他方法所抛出的异常:异常总是丢回给调用方 有风险.会抛出异常的程序代码: 负责声明异常:创建Exception对象并抛出 调用该方法的程序代码: 在try中调用程 ...