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

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

一、说明


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时,将创建非核心线程,核心线程默认情况下不会被回收,不受时间限制,而超时的非核心线程将被回收



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



2.DiscardPolicy


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


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


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



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加进队列中执行



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也可以直接执行



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



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());



目录
相关文章
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
121 1
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
137 1
|
2月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
124 0
|
2月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
193 16
|
3月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
3月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
4月前
|
存储 Java 大数据
Java 大视界 -- Java 大数据在智能家居能源消耗模式分析与节能策略制定中的应用(198)
简介:本文探讨Java大数据技术在智能家居能源消耗分析与节能策略中的应用。通过数据采集、存储与智能分析,构建能耗模型,挖掘用电模式,制定设备调度策略,实现节能目标。结合实际案例,展示Java大数据在智能家居节能中的关键作用。
|
4月前
|
存储 数据采集 数据可视化
Java 大视界 -- 基于 Java 的大数据可视化在城市交通拥堵溯源与治理策略展示中的应用(191)
本项目探索了基于Java的大数据可视化技术在城市交通拥堵溯源与治理策略中的应用。通过整合多源交通数据,利用Java生态中的大数据处理与可视化工具,构建了交通拥堵分析模型,并实现了拥堵成因的直观展示与治理效果的可视化评估。该方案为城市交通管理提供了科学、高效的决策支持,助力智慧城市建设。
|
4月前
|
存储 分布式计算 Java
Java 大视界 -- Java 大数据在智能建筑能耗监测与节能策略制定中的应用(182)
本文探讨了Java大数据技术在智能建筑能耗监测与节能策略制定中的关键应用。通过Hadoop、Spark等技术实现能耗数据的存储、分析与可视化,结合实际案例,展示了Java大数据如何助力建筑行业实现节能减排目标。

热门文章

最新文章