Java的自定义线程池

Java的自定义线程池

自定义线程池的原因

在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面使线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等创建线程池的方法,但都有其局限性,不够灵活,而且有资源耗尽的风险(OOM - Out Of Memory )。

一般我们创建线程池时,为防止资源被耗尽,任务队列都会选择创建有界任务队列,但这种模式下如果出现任务队列已满且线程池创建的线程数达到你设置的最大线程数时,这时就需要你指定ThreadPoolExecutor的RejectedExecutionHandler参数即合理的拒绝策略,来处理线程池"超载"的情况

自定义线程池

在Java中,可以通过ThreadPoolExecutor类来自定义线程池。

import java.util.concurrent.*;public class CustomThreadPoolExample {public static void main(String[] args) {int corePoolSize = 2;int maxPoolSize = 4;long keepAliveTime = 10;int queueSize = 2;ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,TimeUnit.SECONDS,new ArrayBlockingQueue<>(queueSize));for (int i = 1; i <= 6; i++) {final int task = i;threadPool.execute(() -> {System.out.println("Task " + task + " is running on thread: " + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Task " + task + " is completed");});}threadPool.shutdown();}
}

分析:在这个示例中,我们创建了一个ThreadPoolExecutor实例,指定了核心线程数、最大线程数、线程空闲时间、工作队列等参数。然后通过execute方法提交任务给线程池执行。任务会在空闲线程中执行,如果线程数达到最大线程数,多余的任务会被放入工作队列中等待执行。最后记得调用shutdown方法关闭线程池。

注意:你可以根据自己的需求调整线程池的参数,以满足不同的场景要求。

自定义拒绝策略的原因

自定义拒绝策略是为了更好地控制线程池在无法接受新任务时的行为,根据实际需求来定义适合当前场景的处理方式。以下是一些常见的情况,说明为什么需要自定义拒绝策略:

  1. 避免任务丢失: 默认的拒绝策略是直接抛出RejectedExecutionException异常,导致提交的任务丢失。如果希望在任务无法执行时进行处理,比如记录日志、重新提交任务等,就需要自定义拒绝策略来避免任务丢失。
  2. 优雅降级: 在系统负载过高或资源不足时,可以通过自定义拒绝策略来实现任务的优雅降级,比如拒绝新任务、延迟处理、限流等,以保护系统稳定性。
  3. 灵活适配业务需求: 不同的业务场景可能需要不同的处理方式,通过自定义拒绝策略可以灵活适配业务需求,实现定制化的处理逻辑。
  4. 监控和报警: 自定义拒绝策略可以用于监控线程池的状态,比如当线程池达到一定负载时触发报警机制,及时发现问题并进行处理。

总之,自定义拒绝策略可以帮助开发人员更好地控制线程池的行为,提高系统的稳定性和可维护性,同时根据具体业务需求来定制适合的处理方式。

自定义拒绝策略

要自定义拒绝策略,你可以实现RejectedExecutionHandler接口,并重写rejectedExecution方法来定义自己的拒绝逻辑。

import java.util.concurrent.*;public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {System.out.println("Task rejected. Custom handling logic here.");// 可以根据自己的需求实现不同的拒绝逻辑,比如抛出异常、记录日志等}public static void main(String[] args) {int corePoolSize = 2;int maxPoolSize = 4;long keepAliveTime = 10;int queueSize = 2;ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,TimeUnit.SECONDS,new ArrayBlockingQueue<>(queueSize),new CustomRejectedExecutionHandler());for (int i = 1; i <= 6; i++) {final int task = i;threadPool.execute(() -> {System.out.println("Task " + task + " is running on thread: " + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Task " + task + " is completed");});}threadPool.shutdown();}
}

分析:在这个示例中,我们创建了一个CustomRejectedExecutionHandler类来实现自定义的拒绝策略,重写了rejectedExecution方法。然后在创建ThreadPoolExecutor实例时,将这个自定义的拒绝策略传入构造函数中。

注意:当线程池无法接受新任务时,就会调用自定义的拒绝策略中的rejectedExecution方法来处理。你可以根据具体需求,在这个方法中实现自定义的拒绝逻辑,比如抛出异常、记录日志、丢弃任务等。

示例

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Test01 {/*** 知识点:自定义线程池*/public static void main(String[] args) {FastThreadPool pool = new FastThreadPool(5, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(30));for (int i = 1; i <= 100; i++) {Task task = new Task(i);pool.execute(task);}//设置为true后,闲置时间一旦到达,核心线程也会被销毁//经验:我们一般不会回收核心线程,因为设置回收后线程池中的线程有可能为0,这样就没有线程复用率的说法了//pool.allowCoreThreadTimeOut(true);pool.shutdown();}
}//自定义线程池
public class FastThreadPool extends ThreadPoolExecutor{public FastThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, new FastThreadFactory(), new FastRejectedExecutionHandler());}public FastThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);}@Overrideprotected void beforeExecute(Thread t, Runnable r) {System.out.println("线程执行任务之前调用 -- " + r);}@Overrideprotected void afterExecute(Runnable r, Throwable t) {System.out.println("线程执行任务之后调用 -- " + r);}@Overrideprotected void terminated() {System.out.println("线程池关闭时调用");}//自定义线程工厂private static class FastThreadFactory implements ThreadFactory{private int num;//线程编号@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r);t.setName("自定义线程池中的线程"+num);t.setPriority(Thread.MAX_PRIORITY);num++;return t;}}//自定义拒绝策略private static class FastRejectedExecutionHandler implements RejectedExecutionHandler{@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {System.out.println("任务被拒绝了~~~");}}}
public class Task implements Runnable{private int num;public Task(int num) {this.num = num;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "处理了第" + num + "个任务");}@Overridepublic String toString() {return "任务" + num;}
}

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

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

相关文章

docker容器内的进程启动监控,容器进程所在的PID namespce

在容器内启动进程 docker exec -it 9c6b0b0509da /bin/bash cd /home ./testapp 主机上的监控程序同样可以监控到 13022 /home/testapp !!!!!发现异常进程:testapp, exePath:/home/testapp GetExePath()函数返回的值是/home/testapp &#xff0c;即&#xff1a;进程执行文件所…

不能在子类的初始化列表中初始化父类的成员

不能在子类的初始化列表中初始化父类的成员 错误示例代码 class A { protected:int n_; };class B : public A { public:B() : n_(0){} };编译报错如下&#xff1a; error: class ‘B’ does not have any field named ‘n_’前置知识 继承情况下的初始化顺序 子类对象的构…

FFmpeg: 自实现ijkplayer播放器--08视频解码线程设计

文章目录 视频解码解码流程视频解码线程音频解码线程数据帧队列类型定义数据帧队列api视频解码 视频解码,读取数据包(packet),生成数据帧(frame),放入数据帧队列,用来输出音频和视频 解码流程 stream_component_open: 分配解码器上下文 avcodec_alloc_context3将码…

高频九问:产品经理面试题解析

01 ▼ 需求评审时研发说需求实现不了怎么办&#xff1f; 1.站在技术的角度&#xff0c;了解无法实现的原因 2.看有哪些可以替代的方案 3.评估替代方案对项目本身的影响&#xff0c;如延迟&#xff0c;如若在可接受范围内&#xff0c;适当的妥协 02 ▼ 是否了解我们公司&a…

Flume配置案例@Source:文件,Channel+Sink:Kafka

Source&#xff1a;某个目录下所有文件 Channel&#xff1a;Kafka Sink&#xff1a;Kafka 【Source和Channel的选择】 1&#xff09;TailDirSource TailDirSource相比ExecSource、SpoolingDirectorySource的优势。 TailDirSource&#xff1a;断点续传、多目录。Flume1.6以前…

大模型微调技术概览解读(chatGLM-6B)

目录 一些比较流行的PEFT方案 Prompt Tuning Prefix Tuning LoRA QLoRA 引用链接 参考文档&#xff1a;通俗解读大模型微调(Fine Tuning) - 知乎 从参数规模的角度&#xff0c;大模型的微调分成两条技术路线&#xff1a; 一条是对全量的参数&#xff0c;进行全量的训练…

【从零开始手搓12306项目】五、如何保证不超卖、不少卖、还能承受极高的并发?

逻辑设计&模型实现 余票查询&#xff1a;记录站站余票 座位购买&#xff1a;记录座位销售详情&#xff08;将卖票变成01二进制数的计算&#xff09; 使用事务保证原子性

VMware设置静态ip:以Centos7为例

1、获取网段&#xff0c;子网掩码和网关 到此获取到的信息&#xff1a; 网段&#xff1a;192.168.204.128 ~ 192.168.204.254 子网掩码&#xff1a;255.255.255.0 网关IP&#xff1a;192.168.204.2 2、修改Centos系统的网络配置 使用命令vim /etc/sysconfig/network-scripts/…

Kotlin从0到1,让你一周快速上手!!

声明 大家好&#xff0c;这里是懒羊羊学长&#xff0c;如果需要pdf版以及其他资料&#xff0c;请加入群聊。群里每天更新面经、求职资料&#xff0c;经验分享等&#xff0c;大家感兴趣可以加一下。 Kotlin 声明1.Kotlin基础2. Kotlin函数3.Kotlin进阶4.Kotlin集合5.Kotlin高…

全球顶级的低代码开发平台,你知道几个?

什么是低代码开发平台? 低码开发平台是一个应用程序,提供图形用户界面编程,从而以非常快的速度开发代码,减少了传统的编程工作。 这些工具有助于快速开发代码,最大限度地减少手工编码的努力。这些平台不仅有助于编码,而且还能快速安装和部署。 低码开发工具的好处 低代码平…

【QT教程】QT6数据库操作

QT6数据库操作 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C扩展开发视频课程 免费QT视频课程 您可以看免费1000个QT技术视频 免费QT视频课程 QT统计图和QT数据可视化视频免费看 免费QT视频课程 QT性能优化视频免费看 免费Q…

为什么公共云的弹性能力很难被发挥出来?

作者&#xff5c;王小瑞 AutoMQ 联合创始人 & CEO 云计算通过资源池化实现单位资源成本更优&#xff0c;使企业能够将 IDC 建设、基础软件研发和运维等工作外包给云厂商&#xff0c;从而更专注于业务创新。资源池不仅包括服务器&#xff0c;还包括人才。云厂商集聚了优秀…

ubuntu20.04.3挂载共享文件夹

VMware设置win共享文件夹 在linux执行挂载命令 sudo vmhgfs-fuse /mnt/hgfs/ -o nonempty这样就可以用管理员访问/mnt/hgfs/share

Java全套智慧校园系统源码springboot+elmentui +Quartz可视化校园管理平台系统源码 建设智慧校园的5大关键技术

Java全套智慧校园系统源码springbootelmentui Quartz可视化校园管理平台系统源码 建设智慧校园的5大关键技术 智慧校园指的是以物联网为基础的智慧化的校园工作、学习和生活一体化环境&#xff0c;这个一体化环境以各种应用服务系统为载体&#xff0c;将教学、科研、管理和校园…

Docker仅需3步搭建免费私有化的AI搜索引擎-FreeAskInternet

简介 FreeAskInternet 是一个完全免费、私有且本地运行的搜索引擎&#xff0c;并使用 LLM 生成答案&#xff0c;无需 GPU。用户可以提出问题&#xff0c;系统会进行多引擎搜索&#xff0c;并将搜索结果合并到ChatGPT3.5 LLM中&#xff0c;并根据搜索结果生成答案。 什么是 Fr…

3D视觉引导麻袋拆垛破包 | 某大型化工厂

客户需求 此项目为大型化工厂&#xff0c;客户现场每日有大量麻袋拆垛破包需求&#xff0c;麻袋软包由于自身易变形、码放垛型不规则、运输后松散等情况&#xff0c;无法依靠机器人示教位置完成拆垛。客户遂引入3D视觉进行自动化改造。 工作流程&#xff1a; 3D视觉对紧密贴合…

win10系统自带的md5文件校验用法

开始--运行&#xff0c;回车 certutil -hashfile 文件名 md5 其它功能可以看链接&#xff1a;certutil | Microsoft Learn

《剑指 Offer》专项突破版 - 面试题 107 : 矩阵中的距离(C++ 实现)

题目链接&#xff1a;矩阵中的距离 题目&#xff1a; 输入一个由 0、1 组成的矩阵 M&#xff0c;请输出一个大小相同的矩阵 D&#xff0c;矩阵 D 中的每个格子是矩阵 M 中对应格子离最近的 0 的距离。水平或竖直方向相邻的两个格子的距离为 1。假设矩阵 M 中至少有一个 0。 …

JavaScript事件监听测试代码

效果图 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>信息填写页面</title><link …

反射【获取class对象、 操作属性、方法】

day38下 反射 前言 使用到一个类&#xff0c;JVM会将该类的class文件加载到方法区&#xff08;类加载机制&#xff09;&#xff0c; 同时会在堆内存中创建该类的class对象&#xff0c;class对象的作为class文件的访问入口 Java的反射机制 ​ JAVA反射机制是在运行状态中&…