【Java并发编程】线程池的四种拒绝策略(饱和策略)

news2024/10/21 10:15:40

引入

线程池的拒绝策略是当线程池出现以下情况时,由于线程池达到其容量上限而无法接受新任务时的处理机制:

  1. 线程池已满:当线程池中的所有线程都在执行任务时,新提交的任务无法立即执行。这种情况发生在当前线程池的核心线程和最大线程数都已被占用时。
  2. 任务队列已满:当线程池的任务队列(如 LinkedBlockingQueue)已满,新的任务无法被放入队列中等待执行。

在 Java 的并发包(java.util.concurrent)中,ThreadPoolExecutor 提供了四种内置的线程池拒绝策略 (RejectedExecutionHandler)来应对线程池达到其容量限制时,采取适当的策略来处理这些额外的任务。
四种内置拒绝策略适用场景如下,在挑选拒绝策略时需要根据具体的需求选择合适的策略:

策略说明适用场景
AbortPolicy抛出 RejectedExecutionException任务执行必须完成,不能丢失任务的场景,如实时数据处理系统。
CallerRunsPolicy调用 execute() 方法在调用线程中运行任务任务提交者自己执行任务,适用于负载较低时避免任务丢失的场景。
DiscardPolicy忽略被拒绝的任务,不做任何处理任务丢失可以接受,优先处理重要任务的场景,如缓存更新。
DiscardOldestPolicy丢弃队列中最旧的任务并尝试提交新任务需要保留最新任务,但可以丢弃较旧任务的场景,如短时间内的数据采集。

线程池的四种拒绝策略

1. AbortPolicy

默认的拒绝策略。如果线程池和队列都满了,并且无法接受新任务时,AbortPolicy 策略会直接终止任务提交并抛出 RejectedExecutionException 异常。

new ThreadPoolExecutor.AbortPolicy();

使用这种策略时,调用者需要处理异常,确保程序不会因为任务被拒绝而崩溃。适用于任务提交者可以控制和处理异常的场景。

示例

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, 2, 60, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(2),
    new ThreadPoolExecutor.AbortPolicy()
);

2. CallerRunsPolicy

当任务被拒绝时,CallerRunsPolicy 策略会由任务提交者线程来执行被拒绝的任务,而不是由线程池中的线程来执行。

new ThreadPoolExecutor.CallerRunsPolicy();

这种策略可以减缓任务提交的速度,避免过度负荷线程池。适用于希望通过降低提交速率来缓解线程池压力的场景。

示例

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, 2, 60, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(2),
    new ThreadPoolExecutor.CallerRunsPolicy()
);

3. DiscardPolicy

当任务被拒绝时,DiscardPolicy 策略会将被拒绝的任务丢弃,没有任何通知或异常抛出。

new ThreadPoolExecutor.DiscardPolicy();

这种策略采取丢弃任务的方式可能会导致任务丢失,但有助于防止线程池崩溃或性能严重下降,适用于对丢弃任务没有特别要求的场景。

示例

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, 2, 60, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<>(2),
    new ThreadPoolExecutor.DiscardPolicy()
);

4. DiscardOldestPolicy

如果线程池和队列都满了,DiscardOldestPolicy 会丢弃任务队列中最旧的任务,然后尝试提交新的任务。

new ThreadPoolExecutor.DiscardOldestPolicy();

这种策略可以确保新的任务被处理,但会丢弃最早的任务,可能会丢失一些重要任务。适用于希望保留最新任务的场景。

示例

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, 2, 0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<>(2),
    new ThreadPoolExecutor.DiscardOldestPolicy()
);

自定义拒绝策略

除了内置的策略,我们可以通过实现自定义的 RejectedExecutionHandler 接口来创建自定义拒绝策略。

public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 自定义处理逻辑,比如记录日志、重新排队等
        System.out.println("任务被拒绝: " + r.toString());
    }
}

例如,我们可以实现一个自定义的拒绝策略,当任务被拒绝时会尝试重试提交任务:

public class RequeueRejectedExecutionHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 将被拒绝的任务重新排队
        System.out.println("任务被拒绝,正在重新排队: " + r.toString());

        // 尝试将任务重新提交到线程池
        if (!executor.isShutdown()) {
            try {
                Thread.sleep(1000);
                // 直接调用execute方法进行重新排队
                executor.execute(r);
            } catch (Exception e) {
                System.err.println("重新提交任务失败: " + e.getMessage());
            }
        }
    }
}

但是在实际应用中,我们应避免任务被无限重试,应该确保在达到最大重试次数后,任务能够被丢弃或者按照某种策略处理。

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

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

相关文章

spring boot yml文件中引用*.properties文件中的属性

1、首先在*.properties文件中加入一个属性&#xff0c;如&#xff1a; 2、然后再application.yml文件中通过${jdbc.driver}来引用&#xff0c;如&#xff1a; 3、然后再创建一个资源配置类&#xff0c;通过PropertySource来引入这个*.properties文件&#xff0c;如&#xff1…

JDK中socket源码解析

目录 1、Java.net包 1. Socket通信相关类 2. URL和URI处理类 3. 网络地址和主机名解析类 4. 代理和认证相关类 5. 网络缓存和Cookie管理类 6. 其他网络相关工具类 2、什么是socket&#xff1f; 3、JDK中socket核心Api 4、核心源码 1、核心方法 2、本地方法 3、lin…

基于stm32的esp8266的WIFI控制风扇实验

实验案例&#xff37;&#xff29;&#xff26;&#xff29;控制风扇 项目需求 电脑通过esp8266模块远程遥控风扇。 项目框图 ​ 风扇模块封装 #include "sys.h" #include "fan.h"void fan_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开时钟…

4K Mini-LED显示器平民价,一千多的联合创新27M3U到底有多香

哈喽小伙伴们好&#xff0c;我是Stark-C~ 要说前几年买显示器还是普通IPS的天下&#xff0c;那个时候虽说也有MiniLED或者OLED显示器&#xff0c;但是价格那也是真贵啊&#xff0c;毕竟那个时候MiniLED和OLED还没普及&#xff0c;只有一些高档电视或者显示器才会用到此技术。不…

OpenCV高级图形用户界面(18)手动设置轨迹条(Trackbar)的位置函数setTrackbarPos()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数设置指定窗口中指定轨迹条的位置。 注意 [仅 Qt 后端] 如果轨迹条附加到控制面板&#xff0c;则 winname 可以为空。 函数原型 void cv…

三周精通FastAPI:4 使用请求从客户端(例如浏览器)向 API 发送数据

FastAPI官网手册&#xff1a;https://fastapi.tiangolo.com/zh/tutorial/query-params/ 上节内容&#xff1a;三周精通FastAPI&#xff1a;3 查询参数 请求 FastAPI 使用请求从客户端&#xff08;例如浏览器&#xff09;向 API 发送数据。 请求是客户端发送给 API 的数据。响…

国家信息安全水平考试(NISP一级)最新题库-第十六章

目录 另外免费为大家准备了刷题小程序和docx文档&#xff0c;有需要的可以私信获取 1 防火墙是一种较早使用、实用性很强的网络安全防御技术&#xff0c;以下关于防火墙说法错误的是&#xff08;&#xff09; A.防火墙阻挡对网络的非法访问和不安全数据的传递&#xff1b;B.防…

Leecode刷题之路第27天之移除元素

题目出处 27-移除元素-题目描述 题目描述 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。假设 nums 中不等于 val 的元素数量为 k&#xff0c;要通过此题&#x…

C++ | Leetcode C++题解之第491题非递减子序列

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> temp; vector<vector<int>> ans;void dfs(int cur, int last, vector<int>& nums) {if (cur nums.size()) {if (temp.size() > 2) {ans.push_back(temp);}return;}if…

【题解】—— LeetCode一周小结42

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结41 14.鸡蛋掉落 题目链接&#xff1a;887. 鸡蛋掉落 给你 k 枚…

c++迷宫游戏

1、问题描述 程序开始运行时显示一个迷宫地图&#xff0c;迷宫中央有一只老鼠&#xff0c;迷宫的右下方有一个粮仓。游戏的任务是使用键盘上的方向健操纵老鼠在规定的时间内走到粮仓处。 基本要求: 老鼠形象可以辨认,可用键盘操纵老鼠上下左右移动&#xff1b;迷宫的墙足够结…

博弈论学习笔记【施工中】

SG函数 首先定义就不用我讲了吧&#xff0c;还不会的自己看看 传送门 再进一步理解一下吧&#xff1a; 黑色数字是节点编号&#xff0c;红色是 S G SG SG 函数值 看下它的过程&#xff1a; 首先 5 5 5 和 6 6 6 没有后继节点&#xff0c;为必败态&#xff0c;先赋值为 …

OpenCV和HALCON

OpenCV和HALCON是两种广泛用于图像处理和计算机视觉的开发库&#xff0c;它们各有优缺点&#xff0c;适合不同的应用场景。以下是两者的比较&#xff1a; 1. 开发背景与定位 OpenCV (Open Source Computer Vision Library)&#xff1a; 开源库&#xff0c;最初由Intel开发&…

【图解版】力扣第146题:LRU缓存

力扣第146题&#xff1a;LRU缓存 一、LRU算法1. 基本概念2. LRU 和 LFU 的区别&#xff1a;3. 为什么 LRU 不需要记录使用频率&#xff1f; 二、Golang代码实现三、代码图解1. LRUCache、DLinkedNode两个结构体2. 初始化结构体对象3. addToHead函数4. removeNode函数5. moveToH…

基于单片机的多功能鱼缸控制系统设计

本设计以STC12C5A60S2单片机为核心的多功能鱼缸控制系统&#xff0c;该系统可分别利用温度传感器、水位传感器和浑浊度传感器来检测鱼缸内部的水温、液体高度和浑浊程度&#xff0c;并在显示屏上进行显示。若检测结果超出阈值范围&#xff0c;则继电器工作从而控制内部环境。通…

LeetCode102. 二叉树的层序遍历(2024秋季每日一题 43)

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] 示例 2&#xff1a; 输入…

白嫖正版xshell和XFTP

在哪里可以下载正版免费的xshell和XFTP&#xff0c;并且还能够获得官网免费持久更新 白嫖步骤 首先直接在浏览器搜索xshell官网 点进官网之后直接点击下载 接着点击免费授权页面 进入之后就可以免费下载了 下载安装完成后填写用户名和邮箱并提交&#xff0c;这里就以xshell为…

Veritas NetBackup 10.5 发布,新增功能概览

Veritas NetBackup 10.5 发布&#xff0c;新增功能概览 Veritas NetBackup 10.5 (Unix, Linux, Windows) - 领先的企业备份解决方案 The #1 enterprise backup and recovery solution. 请访问原文链接&#xff1a;https://sysin.org/blog/veritas-netbackup-10/ 查看最新版。…

EditPlus的安装软件包

解压并粘贴到C:\Program Files (x86)中 点击激活密匙,并一直同意 确认并选择默认的位置: 关闭并重新激活密匙 就好了 无需添加快捷方式: 只需要选择任意文件 并选择该应用打开一次即可 通过百度网盘分享的文件&#xff1a;EditPlus_5.0.611.zip 链接&#xff1a;https://pa…

在Debian 11/Debian 10上安装MySQL 5.7

本文借鉴 如何在 Debian 11/Debian 10 上安装 MySQL 5.7 |https://cn.linux-console.net/?p20728 下载安装存储库 安装 根据提示选择mysql5.7即可(会车键选择) wget https://dev.mysql.com/get/mysql-apt-config_0.8.16-1_all.debsudo dpkg -i mysql-apt-config_0.8.16-1_a…