线程池高手进阶:揭秘ThreadPoolExecutor的小妙招!

线程池高手进阶:揭秘ThreadPoolExecutor的小妙招! - 程序员古德

RejectedExecutionHandler总结

ThreadPoolExecutor 是 Java 中用于创建和管理线程池的接口,当线程池中的任务队列已满,并且线程池中的线程数量已经达到最大时,如果再有新的任务提交,就需要一个策略来处理这些无法执行的任务。它 提供了四种拒绝策略,都是 RejectedExecutionHandler 接口的实现,如下:

  1. AbortPolicy(默认策略):直接抛出一个 RejectedExecutionException 异常。
  2. CallerRunsPolicy:调用执行任务的 execute 方法的线程来运行任务,如果执行程序已经关闭,那么任务将被抛弃。
  3. DiscardPolicy:无法执行的任务将被抛弃,不会抛出任何异常。
  4. DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行任务(如果再次失败,则重复此过程)。

以下是使用ThreadPoolExecutor的代码示例,如下:

import java.util.concurrent.*;  
  
public class ThreadPoolExecutorDemo {  
    public static void main(String[] args) {  
        // 创建一个固定大小的线程池  
        int corePoolSize = 2;  
        int maximumPoolSize = 4;  
        long keepAliveTime = 10L;  
        TimeUnit unit = TimeUnit.SECONDS;  
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);  
  
        // 使用不同的拒绝策略  
        RejectedExecutionHandler abortPolicy = new ThreadPoolExecutor.AbortPolicy();  
        RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();  
        RejectedExecutionHandler discardPolicy = new ThreadPoolExecutor.DiscardPolicy();  
        RejectedExecutionHandler discardOldestPolicy = new ThreadPoolExecutor.DiscardOldestPolicy();  
  
        // 创建线程池并设置拒绝策略  
        ThreadPoolExecutor executor1 = new ThreadPoolExecutor(  
                corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, abortPolicy);  
  
        ThreadPoolExecutor executor2 = new ThreadPoolExecutor(  
                corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, callerRunsPolicy);  
  
        ThreadPoolExecutor executor3 = new ThreadPoolExecutor(  
                corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, discardPolicy);  
  
        ThreadPoolExecutor executor4 = new ThreadPoolExecutor(  
                corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, discardOldestPolicy);  
  
        // 提交任务  
        for (int i = 0; i < 10; i++) {  
            final int taskId = i;  
            executor1.execute(() -> System.out.println("Executing task " + taskId + " with AbortPolicy"));  
            executor2.execute(() -> System.out.println("Executing task " + taskId + " with CallerRunsPolicy"));  
            executor3.execute(() -> System.out.println("Executing task " + taskId + " with DiscardPolicy"));  
            executor4.execute(() -> System.out.println("Executing task " + taskId + " with DiscardOldestPolicy"));  
        }  
  
    }  
}

在上面的代码示例中,由于工作队列和线程池的大小都设置得很小,所以提交的任务会很快填满队列和线程池,从而触发拒绝策略,不同的拒绝策略适用于不同的场景,在实际应用中,应该根据具体需求来合理设置线程池的大小、工作队列的容量以及拒绝策略。

ThreadFactory总结

ThreadFactory接口常用于在ThreadPoolExecutor中管理控制线程的名称、优先级、是否守护线程以及其他线程属性。下面是一个简单的ThreadFactory使用案例,案例中定义了一个CustomThreadFactory类,如下代码:

import java.util.concurrent.ThreadFactory;  
import java.util.concurrent.atomic.AtomicInteger;  
  
public class CustomThreadFactory implements ThreadFactory {  
    private final String prefix;  
    private final AtomicInteger threadNumber = new AtomicInteger(1);  
  
    public CustomThreadFactory(String prefix) {  
        this.prefix = prefix;  
    }  
  
    @Override  
    public Thread newThread(Runnable r) {  
        // 创建一个新线程  
        Thread thread = new Thread(r);  
        // 设置线程名称,使用前缀和递增的数字  
        thread.setName(prefix + "-" + threadNumber.getAndIncrement());  
        // 可以设置其他属性,比如优先级、守护状态等  
        // thread.setPriority(Thread.MAX_PRIORITY);  
        // thread.setDaemon(false);  
        return thread;  
    }  
}

在上面代码中:

  1. CustomThreadFactory类实现了ThreadFactory接口,并重写了newThread方法。
  2. 构造函数接受一个prefix参数,用于生成线程名称的前缀。
  3. 使用AtomicInteger来生成唯一的线程编号,确保在多线程环境下编号不会重复。
  4. newThread方法中,创建一个新的Thread对象,并通过setName方法设置线程的名称,这里使用前缀和递增的编号来构建线程名称,方便在日志或调试时识别线程。
  5. 还可以根据需要调用其他Thread方法来设置线程的优先级、守护状态等属性。

如下是CustomThreadFactory的使用方法,如下:

import java.util.concurrent.ThreadPoolExecutor;  
import java.util.concurrent.TimeUnit;  
import java.util.concurrent.SynchronousQueue;  
  
public class ThreadPoolExample {  
    public static void main(String[] args) {  
        // 创建一个具有自定义线程工厂的线程池  
        ThreadPoolExecutor executor = new ThreadPoolExecutor(  
            5, // corePoolSize  
            10, // maximumPoolSize  
            60L, // keepAliveTime  
            TimeUnit.SECONDS, // unit for keepAliveTime  
            new SynchronousQueue<>(), // workQueue  
            new CustomThreadFactory("CustomThreadPool-") // 自定义线程工厂  
        );  
  
        // 提交任务给线程池  
        for (int i = 0; i < 20; i++) {  
            final int taskId = i;  
            executor.submit(() -> {  
                // 执行任务  
                System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());  
            });  
        }  
  
        // 关闭线程池(这通常是在应用程序关闭时完成的)  
        // executor.shutdown();  
    }  
}

关注我,每天学习互联网编程技术 - 程序员古德

END!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

antd 日期选择框增加季度预设范围

测试同学说想要有个季度的预设选择框&#xff0c;方便快速选择季度的开始和结束日期。 antd 的rangepicker是支持预设的 日期选择框 DatePicker - Ant Design 实现方法很简单&#xff0c;按照官网示例用moment初始化一下即可 获取当前一季度的开始日期时间&#xff1a; mom…

系统移植 day2 bootloader->u-boot 移植

一、栈的复习 1、满栈&#xff1a;当堆栈指针SP总是指向最后压入堆栈的数据&#xff0c;称为满栈&#xff1b; 2、空栈&#xff1a;当堆栈指针SP总是指向下一个将要放入数据的空位置&#xff0c;称为空栈&#xff1b; 满栈状态下&#xff0c;先移动指针&#xff0c;后赋值. 空…

量化交易学习1

一、股票数据基本分类 可分为&#xff08;1&#xff09;技术面数据和&#xff08;2&#xff09;基本面数据 &#xff08;1&#xff09;技术面数据 技术面数据是通过股票的历史价格和交易量等市场数据进行计算和分析得出的指标。常用的技术指标包括移动平均线、相对强弱指标、…

服务器数据恢复—EVA存储raid5硬盘离线的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌EVA某型号存储&#xff0c;底层是RAID5阵列&#xff0c;划分了若干lun。 服务器故障&分析&#xff1a; 该存储设备中raid5阵列有两块硬盘掉线&#xff0c;存储中的lun丢失。 将故障服务器存储中的所有磁盘编号后取出&#xff0c;硬件…

磁盘d盘满了怎么清理?几个步骤轻松搞定!

当您的电脑D盘快满了的时候&#xff0c;需要对电脑D盘进行清理&#xff0c;以节省空间并使电脑运转更加流畅。下面是一些电脑清理的方法和工具介绍。 一、清理磁盘 1、首先我们打开此电脑 2、然后找到我们要清理的磁盘 3、接着我们右键单击属性选项 4、然后我们点击磁盘清理 …

locust快速入门--自定义用户增长形状

背景&#xff1a; locust 默认的用户增长模式&#xff0c;不方便分析不同用户量大对服务器的压力影响。因此&#xff0c;需要对用户增加的图形进行自定义。 locust官网说明&#xff1a;https://docs.locust.io/en/stable/custom-load-shape.html 自定义不同时间段用户的数量…

Linux 驱动开发基础知识——Hello驱动程序(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

CentOS安装Flume

CentOS安装Flume 一、简介二、安装1、下载2、解压3、创建配置文件4、启动flume agent5、验证 一、简介 Flume is a distributed, reliable, and available service for efficiently collecting, aggregating, and moving large amounts of log data. It has a simple and flexi…

防火墙接口配置实验

1、搭建拓扑 2、给云端添加网络&#xff0c;来实现真机与虚拟机的连接 3、 给防火墙g0/0/0口配置IP&#xff0c;由于我云端绑定的是192.168.100.10&#xff0c;所以这里IP配置为192.168.100.1/24,使用命令开启防火墙远程连接的服务&#xff0c;之后便可通过web远程登陆防火墙 …

JavaScript——forEach()方法

代码示例&#xff1a;数组变量.forEach(值变量名 > {代码块}) //每遍历一个值&#xff0c;就作为形参传入给代码块&#xff0c;执行一次该函数头&#xff0c;继续遍历 举例说明&#xff1a; <script>let arr [1, 2, 3, 4];//arr.forEach(val > {});arr.forEach(v…

OceanBase创建租户

租户是集群之上的递进概念&#xff0c;OceanBase 数据库采用了多租户架构。 集群偏部署层面的物理概念&#xff0c;是 Zone 和节点的集合&#xff0c;租户则偏向于资源层面的逻辑概念&#xff0c;是在物理节点上划分的资源单元&#xff0c;可以指定其资源规格&#xff0c;包括…

大数据平台红蓝对抗 - 磨利刃,淬精兵!

背景 目前大促备战常见备战工作&#xff1a;专项压测&#xff08;全链路压测、内部压测&#xff09;、灾备演练、降级演练、限流、巡检&#xff08;监控、应用健康度&#xff09;、混沌演练&#xff08;红蓝对抗&#xff09;&#xff0c;如下图所示。随着平台业务越来越复杂&a…

滚动条样式修改

对于 Chrome 和 Safari 用户 如果正在使用基于 WebKit 的浏览器&#xff0c;如 Chrome 或 Safari&#xff0c;可以使用以下代码来自定义滚动条样式。将此代码加入到你的 CSS 文件中&#xff1a; /* 设置滚动条的宽度 */ ::-webkit-scrollbar {width: 6px; }/* 设置滚动条轨道…

C++设计模式之迭代器模式

【声明】本题目来源于卡码网&#xff08;https://kamacoder.com/&#xff09; 【提示&#xff1a;如果不想看文字介绍&#xff0c;可以直接跳转到C编码部分】 【设计模式大纲】 【简介】 --什么是迭代器模式&#xff08;第19种设计模式&#xff09; 迭代器模式是⼀种行为设计模…

蓝桥杯---三羊献瑞

观察下面的加法算式: 其中,相同的汉字代表相同的数字,不同的汉字代表不同的数字。 请你填写“三羊献瑞”所代表的4位数字(答案唯一),不要填写任何多余内容。 答案 代码 public class _03三羊献瑞 {public static void main(String[] args) {//c 生 b 瑞 g 献 d 辉…

算法练习-螺旋矩阵(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;数组 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。以下内容均为个人笔记&#xff0c;旨在督促自己认真学习。 题目 给定一个正整数n&#xff0c;生成一个包含1到 n^2 所有元…

BACnet网关BL121BN 实现稳定可靠、低成本、简单的楼宇自控协议BACnet转OPC UA解决方案

随着楼宇自控系统的迅猛发展&#xff0c;人们深刻认识到在楼宇暖通行业中&#xff0c;实时、可靠、安全的数据传输至关重要。在此背景下&#xff0c;高性能的楼宇暖通数据传输解决方案——协议转换网关应运而生&#xff0c;广泛应用于楼宇自控和暖通空调系统应用中。 钡铼技术…

【数据结构】 循环队列的基本操作 (C语言版)

目录 一、顺序队列 1、顺序队列的定义&#xff1a; 2、顺序队列的优缺点&#xff1a; 二、循环队列 1、循环队列的定义&#xff1a; 2、循环队列的优缺点&#xff1a; 三、循环队列的基本操作算法&#xff08;C语言&#xff09; 1、宏定义 2、创建结构体 3、循环队…

PPO学习

openai用tf实现的真的看不懂&#xff0c;大佬的世界… PPO的详细细节 1. 奖励模型和策略的价值头将 query 和 response 的连接作为输入 奖励模型和策略的价值头 不 仅仅查看响应。相反&#xff0c;它将 query 和 response 连接在一起&#xff0c;作为 query_response def ge…

如何群发邮件outlook?外贸邮件群发教程?

outlook怎么设置邮件群发&#xff1f;outlook邮箱群发邮件方法&#xff1f; 在日常生活中&#xff0c;我们经常需要给多个人发送相同的邮件。这时候&#xff0c;群发邮件就显得尤为重要。Outlook作为一款常用的办公软件&#xff0c;提供了强大的邮件群发功能。蜂邮EDM就教大家…
最新文章