ThreadPoolExecutor里面4种拒绝策略(详细)
ThreadPoolExecutor类实现了ExecutorService接口和Executor接口,可以设置线程池corePoolSize,最大线程池大小,AliveTime,拒绝策略等。常用构造方法:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
corePoolSize: 线程池维护线程的最少数量
maximumPoolSize:线程池维护线程的最大数量
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 线程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略
当一个任务通过execute(Runnable)方法欲添加到线程池时:
l 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
2 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
3 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
4 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
handler有四个选择:
ThreadPoolExecutor.AbortPolicy()
抛出java.util.concurrent.RejectedExecutionException异常 ,示例如下:
private static class Worker implements Runnable { public void run() { System.out.println(Thread.currentThread().getName() + " is running"); } } public static void main(String[] args) { int corePoolSize = 5; int maxPoolSize = 10; long keepAliveTime = 5; BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(10); //拒绝策略1:将抛出 RejectedExecutionException. RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor executor = new ThreadPoolExecutor (corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue, handler); for(int i=0; i<100; i++) { executor.execute(new Worker()); } executor.shutdown(); } |
运行结果如下:
pool-1-thread-2 is running
pool-1-thread-3 is running
Exception in thread "main" java.util.concurrent.RejectedExecutionException
pool-1-thread-1 is running
pool-1-thread-7 is running
pool-1-thread-6 is running
pool-1-thread-4 is running
pool-1-thread-9 is running
pool-1-thread-8 is running
pool-1-thread-5 is running
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1760)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:767)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:658)
at concurrent.ThreadPoolDemo.main(ThreadPoolDemo.java:33)
pool-1-thread-10 is running
处理源码如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException(); } |
策略2:ThreadPoolExecutor.CallerRunsPolicy
用于被拒绝任务的处理程序,它直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务。如下:
RejectedExecutionHandler handler =
new ThreadPoolExecutor.CallerRunsPolicy();
运行如下:
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-2 is running
pool-1-thread-3 is running
pool-1-thread-1 is running
pool-1-thread-8 is running
main is running
main is running
main is running
pool-1-thread-4 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
处理源码如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } } |
策略3:
RejectedExecutionHandler handler =
new ThreadPoolExecutor.DiscardOldestPolicy();
这样运行结果就不会有100个线程全部被执行。处理源码如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } } |
策略4:ThreadPoolExecutor.DiscardPolicy
用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。
运行结果也不会全部执行100个线程。
源码如下,实际就是对线程不执行操作:
public static class DiscardPolicy implements RejectedExecutionHandler { /** * Creates a <tt>DiscardPolicy</tt>. */ public DiscardPolicy() { } /** * Does nothing, which has the effect of discarding task r. * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } } |
这四种策略是独立无关的,是对任务拒绝处理的四中表现形式。最简单的方式就是直接丢弃任务。但是却有两种方式,到底是该丢弃哪一个任务,比如可以丢弃当前将要加入队列的任务本身(DiscardPolicy)或者丢弃任务队列中最旧任务(DiscardOldestPolicy)。丢弃最旧任务也不是简单的丢弃最旧的任务,而是有一些额外的处理。除了丢弃任务还可以直接抛出一个异常(RejectedExecutionException),这是比较简单的方式。抛出异常的方式(AbortPolicy)尽管实现方式比较简单,但是由于抛出一个RuntimeException,因此会中断调用者的处理过程。除了抛出异常以外还可以不进入线程池执行,在这种方式(CallerRunsPolicy)中任务将有调用者线程去执行。
ThreadPoolExecutor里面4种拒绝策略(详细)的更多相关文章
- 转载-ThreadPoolExecutor里面4种拒绝策略(详细)
原文链接:https://blog.csdn.net/wjs19930820/article/details/79849050 1 /** * 定义异步任务执行线程池 */ @Configuratio ...
- 线程池ThreadPoolExecutor里面4种拒绝策略
ThreadPoolExecutor类实现了ExecutorService接口和Executor接口,可以设置线程池corePoolSize,最大线程池大小,AliveTime,拒绝策略等.常用构造方 ...
- Java-五种线程池,四种拒绝策略,三种阻塞队列(转)
Java-五种线程池,四种拒绝策略,三种阻塞队列 三种阻塞队列: BlockingQueue<Runnable> workQueue = null; workQueue = n ...
- JUC之线程池-三大方法-七大参数-四种拒绝策略
线程池:重点 三大方法 七大参数 四种拒绝策略 使用池化技术的理由: 我们的程序伴随着创建销毁线程十分浪费资源, 所以使用线程池,先创建线程,随用随取,用完归还 简单来说就是节约了资源. 使用线程池的 ...
- Java 线程池四种拒绝策略
jdk1.5版本新增了 JUC 并发包,其中一个包含线程池. 四种拒绝策略: 拒绝策略类型 说明 1 ThreadPoolExecutor.AbortPolicy 默认拒绝策略,拒绝任务并抛出任务 2 ...
- ThreadPoolExecutor八种拒绝策略浅析
转自:http://www.kailing.pub/article/index/arcid/255.html 前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5 ...
- @EnableAsync @Asnc 以及4种拒绝策略
根据不同的场景,可以选择不同的拒绝策略,如果任务非常重要,线程池队列满了,可以交由调用者线程同步处理. 如果是一些不太重要日志,可以直接丢弃掉. 如果一些可以丢弃,但是又需要知道被丢弃了,可以使用Th ...
- JUC 并发编程--08,线程池,三大方法,七大参数,4种拒绝策略,代码演示
三大方法: //线程池核心线程数为n, 最大线程数为 n ExecutorService fixedThreadPool = Executors.newFixedThreadPool(n); 源码: ...
- Android线程池(二)——ThreadPoolExecutor及其拒绝策略RejectedExecutionHandler使用演示样例
MainActivity例如以下: package cc.vv; import java.util.concurrent.LinkedBlockingQueue; import java.util.c ...
随机推荐
- P4428-[BJOI2018]二进制【树状数组,set】
正题 题目链接:https://www.luogu.com.cn/problem/P4428 题目大意 长度为\(n\)的\(0/1\)串要求支持 修改一个位置 求区间\([l,r]\)有多少个子区间 ...
- react之组件数据挂在方式
1.属性(props) 组件间传值,在React中是通过只读属性 props 来完成数据传递的. props:接受任意的入参,并返回用于描述页面展示内容的 React 元素. import React ...
- 使用CEF(四)— 在QT中集成CEF(1):基本集成
QT作为C++下著名的跨平台软件开发框架,实现了一套代码可以在所有的操作系统.平台和屏幕类型上部署.我们前几篇文章讲解了如何构建一款基于CEF的简单的样例,但这些样例的GUI都是使用的原生的或者是控件 ...
- Python&Selenium 数据驱动测试【unittest+ddt+xml】
一.摘要 本博文将介绍Python和Selenium做自动化测试时,基于unittest框架,借助ddt模块,使用xml文件作为测试输入. 二.xml文件 保存路径:D:\\Programs\\Pyt ...
- 初次认识指针:C语言*p、p以及&p的区别,*p和**p的区别?
https://blog.csdn.net/weixin_43115440/article/details/93475460 先要理解地址和数据,你可以想象有很多盒子,每个盒子有对应的号码,那个号码叫 ...
- vue3.x异步组件
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块 vue2.x 曾经简单的异步组件 components: { AsyncComponent: () =& ...
- [Beta]the Agiles Scrum Meeting 12
会议时间:2020.5.27 21:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 issue yjy 帮助解决技术问题 tq 撰写技术博客 wjx 博客评分界面美化 dzx 博客评分界 ...
- UltraSoft - Alpha - Scrum Meeting 6
Date: Apr 21th, 2020. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM 验证了课程中心获取课程资源和作业的爬虫方式 细化前后端交互中的难 ...
- AlertManager集群搭建
AlertManager集群搭建 一.AlertManager集群搭建 1.背景 2.机器 3.集群可用配置 4.alertmanager启动脚本 1.127.0.0.1:9083 机器启动脚本 2. ...
- 从0到1使用Kubernetes系列(四):搭建第一个应用程序
传统Kubernetes应用搭建 创建Namespace 在一个Kubernetes集群中可以创建多个Namespace进行"环境隔离",当项目和人员众多的时候,可以考虑根据项目的 ...