Java 线程池四种拒绝策略
jdk1.5版本新增了
JUC并发包,其中一个包含线程池。
四种拒绝策略:
| 拒绝策略类型 | 说明 | |
|---|---|---|
| 1 | ThreadPoolExecutor.AbortPolicy | 默认拒绝策略,拒绝任务并抛出任务 |
| 2 | ThreadPoolExecutor.CallerRunsPolicy | 使用调用线程直接运行任务 |
| 3 | ThreadPoolExecutor.DiscardPolicy | 直接拒绝任务,不抛出错误 |
| 4 | ThreadPoolExecutor.DiscardOldestPolicy | 触发拒绝策略,只要还有任务新增,一直会丢弃阻塞队列的最老的任务,并将新的任务加入 |
预先配置
配置线程池。
- 核心线程和最大线程都尽量设置的小一点,分别设置成 1 和 2
- 阻塞队列设置固定长度的有界队列,长度为 1
- 线程工厂设置默认线程工厂
// 核心线程数
int corePoolSize = 1;
// 最大线程数
int maximumPoolSize = 2;
// 线程存活时间
long keepAliveTime = 10;
// 线程存活时间单位
TimeUnit unit = TimeUnit.SECONDS;
// 有界队列 遵循 FIFO 原则
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1);
// 线程工厂
ThreadFactory threadFactory = Executors.defaultThreadFactory();
创建线程任务
创建线程任务,一个线程任务执行一秒:
class TaskThread implements Runnable{
private int i;
public TaskThread(int i) {
this.i = i;
}
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("执行任务:" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
拒绝策略一:AbortPolicy
默认拒绝策略,拒绝任务并抛出任务
// 拒绝策略 默认拒绝策略,拒绝任务并抛出异常:
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler);
for (int i = 1; i <= 5; i++) {
try {
threadPool.execute(new TaskThread(i));
} catch (Exception e) {
System.out.println("【任务" + i + "】报错:" + e.getMessage());
}
}
输出
【任务】4报错:Task com.test.controller.ThreadPoolController$TaskThread@5c0369c4 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
【任务】5报错:Task com.test.controller.ThreadPoolController$TaskThread@31b7dea0 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
执行任务:1
执行任务:3
执行任务:2
最大线程数 + 阻塞队列 = 3,执行到4,5的时候就抛出错误。这里需要用 try catch 捕获异常。任务1、2、3正常执行。
如果提交的任务都要执行,可以将抛出的错误任务存入在redis中,然后定时从
redis中获取任务,再提交执行。
拒绝策略二:CallerRunsPolicy
调用线程运行多余的任务。
更换拒绝策略,将上面的 AbortPolicy 换成 CallerRunsPolicy。
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
执行任务,输出:
执行任务:1
执行任务:4
执行任务:3
执行任务:2
执行任务:5
最大线程数 + 阻塞队列 = 3,多余的任务还是继续被执行。
拒绝策略三:DiscardPolicy
拒绝任务,不会抛出错误。
更换策略,将CallerRunsPolicy 换成DiscardPolicy:
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
执行任务,输出:
执行任务:1
执行任务:3
执行任务:2
多余的线程任务提交被拒绝,而只执行最大线程数 + 阻塞队列 数量的任务,并且不会抛出错误。
拒绝策略四:DiscardOldestPolicy
只要还有任务新增,一直会丢弃阻塞队列的最老的任务,并将新的任务加入到阻塞队列中。
更换策略,将DiscardPolicy 换成DiscardOldestPolicy:
RejectedExecutionHandler handler3 = new ThreadPoolExecutor.DiscardOldestPolicy();
执行任务,输出:
执行任务:3
执行任务:1
执行任务:5
任务的执行顺序是 核心线程数 —> 阻塞队列 —> 最大线程数,其中任务1,任务3提交成功。
- 任务2因为在阻塞队列中,
- 后面的任务4把任务2挤掉,
- 任务5又把任务4挤掉,所以最后执行的是任务5。
总结
本文介绍了线程四种拒绝策略,当工作任务大于最大线程 + 阻塞队列会执行阻塞队列。
- AbortPolicy 默认策略,拒绝任务,并抛出异常
- CallerRunsPolicy 调用线程执行对于的任务
- DiscardPolicy 拒绝任务,不会抛出异常
- DiscardOldestPolicy 有多余的任务,把阻塞队列最老的任务丢弃,放入新的任务,直到没有新的任务。
如果觉得文章对你有帮助的话,请点个推荐吧!
Java 线程池四种拒绝策略的更多相关文章
- Java 线程池 8 大拒绝策略,面试必问!
前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发.而不论你用Fix ...
- Java-五种线程池,四种拒绝策略,三种阻塞队列(转)
Java-五种线程池,四种拒绝策略,三种阻塞队列 三种阻塞队列: BlockingQueue<Runnable> workQueue = null; workQueue = n ...
- JUC之线程池-三大方法-七大参数-四种拒绝策略
线程池:重点 三大方法 七大参数 四种拒绝策略 使用池化技术的理由: 我们的程序伴随着创建销毁线程十分浪费资源, 所以使用线程池,先创建线程,随用随取,用完归还 简单来说就是节约了资源. 使用线程池的 ...
- windows线程池四种情形(win核心读书笔记)
windows线程池四种情形(win核心读书笔记) Mircosoft从Windows2000引入线程池API,并在Vista后对线程池重新构架,引入新的线程池API.以下所有线程池函数均适用于Vis ...
- Java线程池底层源码分享和相关面试题(持续更新)
线程池各个参数讲解 public ThreadPoolExecutor(int corePoolSize, //线程池核心工作线程数量,比如newFixedThreadPool中可以自定义的线程数量就 ...
- 《Java线程池》:任务拒绝策略
在没有分析线程池原理之前先来分析下为什么有任务拒绝的情况发生. 这里先假设一个前提:线程池有一个任务队列,用于缓存所有待处理的任务,正在处理的任务将从任务队列中移除.因此在任务队列长度有限的情况下就会 ...
- Java线程池的拒绝策略
一.简介 jdk1.5 版本新增了JUC并发编程包,极大的简化了传统的多线程开发.前面文章中介绍了线程池的使用,链接地址:https://www.cnblogs.com/eric-fang/p/900 ...
- Java 线程池框架核心代码分析--转
原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...
- Java 线程池框架核心代码分析
前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和资源消耗都是很高的.线程池应运而生,成为我们管理线程的利器.Java 通过Executor接口,提供了一种标准的方法将任务的提交过 ...
随机推荐
- 【ASP.NET Core】MVC模型绑定:自定义InputFormatter读取CSV内容
在上一篇文章中,老周介绍了用自定义 ModelBinder 的方式实现一个 API(或MVC操作方法)可以同时支持 JSON 格式和 Form-data 格式的数据正文.今天该轮到 InputForm ...
- Linux 环境部署Skywalking支持Elasticsearch
一.环境准备 1.Java JKD 1.8(建议) 2.Elasticsearch 3.Skywalking 二. 环境搭建 安装Skywalking分为两个步骤: a.安装Backend后端服务 b ...
- java-iov概念
Ioc-Inversion of Control 即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象 ...
- Zookeeper Watcher 机制 -- 数据变更通知 ?
Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务 端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通 知来实现分布式的通知功 ...
- 使用 Spring 通过什么方式访问 Hibernate?
在 Spring 中有两种方式访问 Hibernate:控制反转 Hibernate Template 和 Callback.继承 HibernateDAOSupport 提供一个 AOP 拦截器.
- C语言之基本语句分类(知识点5)
一.C语言基本语句分类 ①数据定义语句 ②赋值语句 ③函数调用语句 ④表达式语句 ⑤流程控制语句 ⑥复合语句(多个大括号的层次) ⑦空语句 二.注意 ①scanf("%d,%d", ...
- js 遮罩效果
-------------------------------tipswindown.js------------------------------ ///--------------------- ...
- 走在 SVG + Low Poly 的路上
随着 SVG 的发展,艺术家和设计师们把越来越多传统设计行业的东西引入了前端, low poly 就是其中之一.那 low poly 强大在哪呢,大家通过下面的图来感受一下. 恰巧我们产品 Logo ...
- mpvue打包没有app.json等配置文件的解决方法
问题 一早上折腾了1个小时,小程序始终提示查找不到'app.json'文件.mpvue重新打包,光生成内容文件无配置文件. 解决办法 出错原因:版本问题 只需要把packpage.json里的mpvu ...
- java中到底什么是继承?
1.何为继承?What is Inheritance? 在上图中,对于车来讲,汽车就是子类.对于汽车来讲,奔驰就是子类.车是汽车的基类,超类,或说父类.到底什么是继承?马克-to-win,子类把父类的 ...