首页 > 编程语言 >Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略

时间:2022-11-11 10:32:20浏览次数:31  
标签:Java 队列 任务 线程 new 多线程 RejectedExecutionHandler public ThreadPoolExecutor


目录

  • ​​一、说明​​
  • ​​二、理解​​
  • ​​三、实现​​
  • ​​1.AbortPolicy​​
  • ​​2.DiscardPolicy​​
  • ​​3.DiscardOldestPolicy​​
  • ​​4.CallerRunsPolicy​​
  • ​​5.自定义拒绝执行策略​​

一、说明

RejectedExecutionHandler

  • 当线程池已经被关闭,或者任务数超过maximumPoolSize+workQueue时执行拒绝策略
  • ​ThreadPoolExecutor.AbortPolicy​​ 默认拒绝策略,丢弃任务并抛出RejectedExecutionException异常
  • ​ThreadPoolExecutor.DiscardPolicy​​ 直接丢弃任务,但不抛出异常
  • ​ThreadPoolExecutor.DiscardOldestPolicy​​ 丢弃任务队列最先加入的任务,再执行execute方法把新任务加入队列执行
  • ​ThreadPoolExecutor.CallerRunsPolicy​​:由创建了线程池的线程来执行被拒绝的任务

二、理解

AbortPolicy

默认拒绝策略,丢弃任务并抛出RejectedExecutionException异常

private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
public static class AbortPolicy implements RejectedExecutionHandler {r
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}

DiscardPolicy

直接丢弃任务,但不抛出异常

public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}

DiscardOldestPolicy

丢弃队列中等待最久的任务,再把新任务添加进去执行,从任务队列弹出最先加入的任务,空出一个位置,然后再次执行execute方法把任务加入队列

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}

CallerRunsPolicy

会调用当前线程池的所在的线程去执行被拒绝的任务

public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}

三、实现

1.AbortPolicy

创建 ​​ThreadPoolExecutorTest​​​类,默认使用​​ThreadPoolExecutor.AbortPolicy​​​拒绝策略,队列是​​ArrayBlockingQueue​​,设置核心线程数最大值为1,线程池线程数最大值为2,最大等待时间为5秒,等待队列值为2

public class RejectedExecutionHandlerTest {
public static void main(String[] args) throws InterruptedException {
// 1.创建自定义线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());


// 2.创建线程任务
for (int i = 1; i <= 6; i++) {

// 3.执行任务
System.out.println("执行第"+i+"个任务");
threadPoolExecutor.execute(new runnable("任务"+i));

System.out.println("当前核心线程数" + threadPoolExecutor.getCorePoolSize());
System.out.println("当前线程池线程数" + threadPoolExecutor.getPoolSize());
// 4.迭代器获取等待队列
Iterator iterator = threadPoolExecutor.getQueue().iterator();
System.out.print("当前等待队列 ");
while (iterator.hasNext()){
runnable thread = (runnable) iterator.next();
System.out.print(thread.name + "\t");
}
System.out.print("\n");
System.out.println("--------");
}

Thread.sleep(10000);
System.out.println("----休眠10秒后----");
System.out.println("当前核心线程数" + threadPoolExecutor.getCorePoolSize());
System.out.println("当前线程池线程数" + threadPoolExecutor.getPoolSize());
System.out.println("当前队列任务数" + threadPoolExecutor.getQueue().size());

// 5.关闭线程池
threadPoolExecutor.shutdown();
}
// 实现Runnable
static class runnable implements Runnable{
// 设置任务名
String name;
public runnable(String setName) {
this.name = setName;
}
@Override
public void run() {
try {
System.out.println("线程:"+Thread.currentThread().getName() +" 执行: "+name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

当线程数达到​​corePoolSize​​后,若有新任务加入,则直接进入任务队列等待,超出队列的任务会创建新的线程来执行

一共有1个核心,当线程数超过​​corePoolSize+workQueue​​时,将创建非核心线程,核心线程默认情况下不会被回收,不受时间限制,而超时的非核心线程将被回收

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_java

但如果再执行1个任务,线程数超过​​maximumPoolSize+workQueue​​​,再提交任务将被丢弃并抛出​​RejectedExecutionException​​异常

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_任务队列_02

2.DiscardPolicy

创建5个任务,让被线程池拒绝的任务直接丢弃,不会抛异常也不会执行

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());

任务5不会执行,恶意不会抛出异常,超时的非核心线程将被回收

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_线程池_03

3.DiscardOldestPolicy

丢弃任务队列最先加入的任务,再执行execute方法把新任务加入队列执行

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());

添加任务5时,线程数已经超过​​maximumPoolSize+workQueue​​,抛弃最先加入队列的任务2并且不执行,再将任务5加进队列中执行

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_任务队列_04

4.CallerRunsPolicy

会调用当前线程池的所在的线程去执行被拒绝的任务

// 1.创建自定义线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());

主线程执行任务1,空闲线程执行任务4,此时队列中有任务2和任务3

添加任务5时,线程数已经超过​​maximumPoolSize+workQueue​​​,任务5直接调用当前线程池的所在的线程​​main​​去执行,这时主线程被阻塞了

当任务5执行完成时,最先的两个任务已经完成了,主线程去执行任务2和任务3,添加任务6也可以直接执行

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_java_05

超时的非核心线程将被回收

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_线程池_06

5.自定义拒绝执行策略

当线程数已经超过​​maximumPoolSize+workQueue​​时,调用新线程去执行任务

static class MyRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
new Thread(r, "新线程"+(new Random().nextInt(4) + 1)).start();
}
}
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new MyRejectedExecutionHandler());

Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_线程池_07


Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略_自定义_08


标签:Java,队列,任务,线程,new,多线程,RejectedExecutionHandler,public,ThreadPoolExecutor
From: https://blog.51cto.com/u_15872973/5843058

相关文章

  • Java多线程 线程池Executor框架
    目录​​一、说明​​​​二、理解​​​​Executor​​​​ExecutorService​​​​Executors​​​​三、实现​​​​1.newSingleThreadExecutor​​​​2.newFixedThr......
  • 8:Spring MVC-Java Spring
    目录​​8.1WEB开发模式一​​​​8.2WEB开发模式二​​​​8.3SpringMVC介绍​​​​8.4SpringMVC主要组件​​​​8.5SpringMVC处理流程​​​​8.6SpringMVC的......
  • Java Web项目中使用RSA加密数据
    在Web项目中有些时候需要对传输的数据加密后再传输到服务端进行解密使用,这里采用RSA进行公钥加密私钥解密的模式会有较高的安全性。这里选用的工具库是 JSEncrypt.js ......
  • 硬核剖析Java锁底层AQS源码,深入理解底层架构设计
    我们常见的并发锁ReentrantLock、CountDownLatch、Semaphore、CyclicBarrier都是基于AQS实现的,所以说不懂AQS实现原理的,就不能说了解Java锁。上篇文章讲了AQS的加锁流程,这......
  • Java并发编程——基础知识(一)
    1.进程与线程1.1基本概念进程:对运行时程序的封装,是系统进行资源调度和分配的的基本单位,实现了操作系统的并发线程:进程的子任务,是CPU调度和分派的基本单位,用于保证程序......
  • Java组合异步编程(2)
    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~ 多数码农在开发的时候,要么处理同步应用,要么处理异步。但是如果能学会使用CompletableFuture,就会具备一种神奇的能力:将同......
  • 定位java程序中占用cpu最高的线程堆栈信息
    找出占用cpu最高的线程堆栈信息在java编码中,有时会因为粗心导致cpu占用较高的情况,为了避免影响程序的正常运行,需要找到问题并解决。这里模拟一个cpu占用较高的场景,并尝试......
  • Java MAC环境Intellij2022配置Servlet和Tomcat
    1、下载安装Tomcat官网:https://tomcat.apache.org/download-90.cgi ->download 下载完放入自定义路径,需要记住!这样算下载好了,详细-> https://blog.csdn.net/qq_44......
  • java学习
    Mardown学习标题:#空格+标题名字几级标题几个#字体Hello,word!Hello,word!Hello,word!Hello,word!Hello,word!引用12345>直接输入引用内容分割线___三个......
  • 【Java】Java基础知识点之集合类型基础概念
    Java常用集合有哪些?Java集合类主要由两个接口Collection和Map派生出来的。Collection有三个子接口:List、Set、Queue。List代表了有序可重复集合,可直接根据元素的索引来访......