Java基础:线程池拒绝策略详解

news2024/11/23 11:18:01

目录

    • 线程池拒绝策略概述
      • 1. AbortPolicy(默认策略)
      • 2. CallerRunsPolicy
      • 3. DiscardPolicy
      • 4. DiscardOldestPolicy
      • 5. 自定义拒绝策略

在Java多线程编程中,线程池(ThreadPool)是一种重要的并发工具,它允许我们创建一组可复用的线程来执行多个任务。然而,当线程池中的线程数达到其最大容量,并且任务队列也满了时,新提交的任务就需要被处理,这时就会用到线程池的拒绝策略。本文将详细介绍Java中ThreadPoolExecutor提供的四种拒绝策略,并探讨它们的特点、使用场景及示例代码。

线程池拒绝策略概述

线程池的拒绝策略是指当线程池无法接受新任务时,如何处理这些被拒绝的任务。ThreadPoolExecutor提供了四种内置的拒绝策略,并且允许用户自定义拒绝策略。

1. AbortPolicy(默认策略)

特点:当任务无法被线程池执行时,会抛出一个RejectedExecutionException异常。

使用场景:适用于对任务丢失敏感的场景,当线程池无法接受新任务时,希望立即知道并处理该异常。

示例代码

import java.util.concurrent.*;

public class AbortPolicyDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 2, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(2),
                new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                System.out.println("Task " + Thread.currentThread().getName() + " is running.");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        executor.shutdown();
    }
}

2. CallerRunsPolicy

特点:当任务无法被线程池执行时,会直接在调用者线程中运行这个任务。如果调用者线程正在执行一个任务,则会创建一个新线程来执行被拒绝的任务。

使用场景:适用于可以容忍任务在调用者线程中执行的业务场景,它允许任务继续执行,而不会因为线程池资源不足而被丢弃。

示例代码

import java.util.concurrent.*;

public class CallerRunsPolicyDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 2, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(2),
                new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                System.out.println("Task " + Thread.currentThread().getName() + " is running.");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        executor.shutdown();
    }
}

3. DiscardPolicy

特点:当任务无法被线程池执行时,任务将被直接丢弃,不抛出异常,也不执行任务。

使用场景:适用于对任务丢失不敏感的场景,当线程池无法接受新任务时,简单地丢弃被拒绝的任务。

示例代码

import java.util.concurrent.*;

public class DiscardPolicyDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 2, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(2),
                new ThreadPoolExecutor.DiscardPolicy());

        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                System.out.println("Task " + Thread.currentThread().getName() + " is running.");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        executor.shutdown();
    }
}

4. DiscardOldestPolicy

特点:当任务无法被线程池执行时,线程池会丢弃队列中最旧的未处理任务,然后尝试重新提交当前任务。

使用场景:适用于对新任务优先级较高的场景,当线程池无法接受新任务时,会丢弃一些等待时间较长的旧任务,以便接受新任务。

示例代码

import java.util.concurrent.*;

public class DiscardOldestPolicyDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 2, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(2),
                new ThreadPoolExecutor.DiscardOldestPolicy());

        for (int i = 0; i < 5; i++) {
            final int taskId = i;
            executor.submit(() -> {
                System.out.println("Executing task " + taskId + " by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        executor.shutdown();
        // 等待所有任务完成(尽管有些任务可能已被丢弃)
        try {
            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

在这个例子中,我们尝试提交了5个任务到一个容量为2的线程池,其中任务队列的最大容量也设置为2。由于DiscardOldestPolicy被用作拒绝策略,当尝试提交第5个任务时,队列中最旧的任务(即第1个任务)将被丢弃,然后尝试重新提交当前任务(但在这个例子中,由于线程池和队列都已满,第5个任务实际上也会被丢弃,因为没有额外的空间来容纳它)。

5. 自定义拒绝策略

除了上述四种内置的拒绝策略外,ThreadPoolExecutor还允许你通过实现RejectedExecutionHandler接口来定义自己的拒绝策略。这提供了极高的灵活性,可以根据具体需求定制拒绝任务的行为。

自定义拒绝策略示例

import java.util.concurrent.*;

public class CustomRejectionPolicy implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 在这里定义你的自定义处理逻辑
        System.out.println("Task " + r.toString() + " was rejected");
        // 可以选择记录日志、抛出异常、使用备用线程池执行等
    }

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 2, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(2),
                new CustomRejectionPolicy());

        // 提交任务...
    }
}

在自定义拒绝策略中,你可以访问被拒绝的任务(Runnable r)和线程池实例(ThreadPoolExecutor executor),从而可以根据这些信息来做出决策,比如记录日志、抛出异常、将任务提交到另一个线程池等。

线程池拒绝策略是处理超出线程池处理能力的任务的一种方式。Java提供了四种内置的拒绝策略,每种策略都有其适用场景。然而,在复杂的应用场景中,这些内置策略可能无法满足需求,此时可以通过实现自定义拒绝策略来灵活处理。无论是使用内置策略还是自定义策略,都需要根据应用的具体需求和资源状况来合理选择,以确保系统的稳定性和高效性。

在设计系统时,合理配置线程池的大小、任务队列的容量以及选择合适的拒绝策略,对于提高系统的并发处理能力和稳定性至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录 day 32 动态规划

第九章 动态规划part01 今天正式开始动态规划&#xff01; 理论基础 无论大家之前对动态规划学到什么程度&#xff0c;一定要先看 我讲的 动态规划理论基础。 如果没做过动态规划的题目&#xff0c;看我讲的理论基础&#xff0c;会有感觉 是不是简单题想复杂了&#xff1f; …

0208-场景状态模式的UML图

一、设置状态 二、Uml类图

白话Java - 守护线程

全文详见个人独立博客&#xff1a;白话Java - 守护线程 白话Java - 守护线程关于”白话”, 偶然想到的词。目的就是用简洁&#xff0c;明快的语言来告诉您&#xff0c;我所知道的一切。 Java中的线程分两类&#xff0c;用户线程和守护线程。 Thread commonThread new Thread(…

尚硅谷谷粒商城项目笔记——七、安装rabbitMQ【电脑CPU:AMD】

七、安装rabbitMQ 注意&#xff1a; 因为电脑是AMD芯片&#xff0c;自己知识储备不够&#xff0c;无法保证和课程中用到的环境一样&#xff0c;所以环境都是自己根据适应硬件软件环境重新配置的&#xff0c;这里的虚拟机使用的是VMware。 [!NOTE] 下载RabbitMQ和Erlang的安装…

最新!2024年—华为认证HCIP考证流程

HCIP HCIP&#xff08;Huawei Certified ICT Professional 华为认证ICT高级工程师&#xff09;是华为职业认证中用于标识个人能力在某一技术领域达到高级工程师级别的证明&#xff0c;表示通过认证的人员具有丰富的ICT知识和实践能力。 HCIP方向 HCIP认证条件 无&#xff0…

蝙蝠避障:盲人出行的守护者,让每一步都安心

在这个多彩的世界里&#xff0c;作为一位盲人&#xff0c;我时常感受着出行的种种挑战。每一次踏出家门&#xff0c;都是一场未知的探险&#xff0c;心里难免有些忐忑。街道上的车流声、人群的喧闹&#xff0c;这些对我而言只是模糊的背景音&#xff0c;真正让我担忧的是那些突…

【AI】OCR篇1

每日更新&#xff0c;建议关注、收藏、点赞 ocr流程 版面分析 、预处理-> 行列切割 -> 字符识别 -> 后处理识别矫正 判断页面上的文本朝向&#xff0c;图像预处理&#xff0c;做角度矫正和去噪。对文档版面进行分析&#xff0c;进每一行进行行分割&#xff0c;把每…

AI/机器学习(计算机视觉/NLP)方向面试复习4

1. 什么是知识图谱&#xff1f; 是结构化的语义知识库&#xff0c;用于迅速描述物理世界中的概念及其相互关系。它的基本单位是(实体-关系-实体) 就是点-线-点。 存储类型有结构化和非结构化的数据。结构化数据就是关系数据库&#xff0c;一张表格&#xff0c;关系很清楚&…

leetcode面试算法题

1.数组/字符串 1.1合并两个有序数组 class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int p1 0;//遍历数组1int p2 0;//遍历数组2int[] nums3 new int[m n];int p 0;while (p1 < m && p2 < n) {//当数组1、2都没遍历完nums3[…

免费分享:中国1平方公里以上湖泊形状数据(附下载方法)

我国是世界上湖泊数量最多的国家之一&#xff0c;共有湖泊24800多个。其中面积在1平方千米以上的天然湖泊就有2800多个。湖泊分布呈现出显著的区域性差异。东部季风区&#xff0c;特别是长江中下游地区&#xff0c;分布着我国最大的淡水湖群&#xff1b;西部以青藏高原湖泊较为…

创新技术引领潮流,2024年录屏软件新技术

现在使用录屏工具的情况越来越多&#xff0c;大家可以用来录制游戏过程、可以用来录制教学视频、可以用来录制会议记录等需要记录屏幕操作的过程。那有什么适合我们自己的录屏工具吗&#xff1f;这次我给你介绍几款我用过的&#xff0c;你看看是不是符合你的需求吧。 1.福晰录…

多云应用安全平台RegData利用MongoDB简化数据控制和合规流程

在高度规范化市场中&#xff0c;为了保障数据安全&#xff0c;企业可能需要部署一系列繁琐且成本高昂的IT基础设施系统。随着各项数据安全保护措施的出台&#xff0c;企业需要遵守的法规数量越多&#xff0c;尤其是跨越多个地域的企业&#xff0c;其IT基础设施就会越复杂。如今…

《程序猿入职必会(9) · 用代码生成器快速开发》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

从文字到视频的魔法:CogVideoX让你的创意瞬间成真

CogVideoX 发布 如果有一个工具能够让你轻松跨越这些障碍&#xff0c;瞬间成为短视频高手&#xff0c;你会心动吗&#xff1f;今天&#xff0c;这个梦想终于成为现实。智谱AI最新推出的CogVideoX&#xff0c;正是为你量身打造的AI视频创作神器&#xff01; CogVideoX CogVideoX…

论文辅导 | 基于时空Transformer 网络的隧道交通运行风险 动态辨识方法

辅导文章 模型描述 为了及时发现、评估与应对高速公路隧道交通风险隐患&#xff0c;确保隧道运行安全通畅&#xff0c;构建了基于时空Transformer网络的隧道运行风险状态动态辨识方法。以隧道交通流全域检测数据与关键断面集计数据为输入&#xff0c;通过空间CNN卷积与时序LST…

蜂窝物联智慧农业新篇章:揭秘智慧大棚的科技魅力!

在这个科技日新月异的时代&#xff0c;农业这一古老而重要的行业正经历着前所未有的变革。智慧农业的兴起&#xff0c;尤其是智慧大棚的应用&#xff0c;正悄然改变着我们对传统农业的认知&#xff0c;引领着农业生产进入了一个高效、精准、可持续发展的新时代。今天&#xff0…

怎么查询大数据信用评分?

相信在了解大数据信用评分的时候&#xff0c;不少人都因为大数据信用评分在申贷的时候遭受到过挫折&#xff0c;因为大数据信用已经被很多银行和金融机构作为风险控制的重要依据使用&#xff0c;其中的大数据信用评分&#xff0c;能直观的感知到用户的信用情况。那如何查询大数…

【ESP-IDF】ESP32获取真随机数

ESP32内置一个真随机数发生器。我翻了好几个型号的ESP32的编程指南&#xff0c;都有相关的函数&#xff0c;应该是大部分型号都有&#xff0c;具体有没有还需要对照一下自己手上的ESP32型号。 我们可以从从随机数发生器的寄存器 RNG_DATA_REG 中读取随机数&#xff0c;每个读到…

到底哪款蓝牙耳机才是性价比之王?精选四款平价高品质耳机品牌!

在当前的音频设备市场中&#xff0c;蓝牙耳机已成为众多现代人挑选的热门配件。选蓝牙耳机不同人看重的点不一样&#xff0c;但倘若像我这样喜欢用来听音乐的&#xff0c;就千万别忽视耳机的音质。现在的产品越来越多&#xff0c;到底哪款蓝牙耳机才是性价比之王&#xff1f;一…

html+css 实现hover背景彩色按钮

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…