自定义线程池-实现任务0丢失的处理策略
设计一个线程池要求如下队列最大容量为10内存队列。当队列满了之后拒绝策略将新的任务写入数据库。从队列中取任务时若该队列为空能够从数据库中加载之前被拒绝的任务1自定义Runnable接口继承Serializable实现可序列化public interface SerializableTask extends Runnable,Serializable { }2 自定义Runable任务序列化public class CustomTask { public static String serializedTask(SerializableTask runnable){ try(ByteArrayOutputStream baos new ByteArrayOutputStream(); ObjectOutputStream oos new ObjectOutputStream(baos)) { // 序列化任务对象 oos.writeObject(runnable); return Base64.getEncoder().encodeToString(baos.toByteArray()); }catch (Exception e){ throw new RuntimeException(无法序列化); } } public static SerializableTask deserialization(String serializedTask){ // 反序列化任务 byte[] data Base64.getDecoder().decode(serializedTask); try (ByteArrayInputStream bais new ByteArrayInputStream(data); ObjectInputStream ois new ObjectInputStream(bais)) { SerializableTask task (SerializableTask) ois.readObject(); return task; }catch (Exception e){ throw new RuntimeException(无法反序列化); } } }3自定义阻塞队列 (DatabaseBackedBlockingQueue)继承LinkedBlockingQueue并重写关键方法take()方法逻辑优先从内存队列取任务队列为空时从数据库加载数据库也为空时阻塞等待新任务offer()方法队列未满时接受满时返回false触发拒绝策略public class CustomBlockQueue extends LinkedBlockingQueueRunnable { private RunnableTaskService runnableTaskService; public CustomBlockQueue(int maxLocalCapacity, RunnableTaskService runnableTaskService) { super(maxLocalCapacity); this.runnableTaskService runnableTaskService; } Override public Runnable take() throws InterruptedException { // 1. 优先检查本地队列 Runnable task super.poll(); if (task ! null){ return task; } // 2. 本地队列为空时尝试从数据库加载 while (true) { System.out.println(Thread.currentThread().getName()进入循环); RunnableTask dbTask runnableTaskService.loadTask(); if (dbTask ! null) { String taskName dbTask.getTaskName(); Runnable deserialization CustomTask.deserialization(taskName); dbTask.setTaskState(1); runnableTaskService.updateRunnableTask(dbTask); return deserialization; } // 3. 数据库为空则等待新任务 if (isEmpty()) { task super.take(); // 阻塞直到有新任务 return task; } } } }4拒绝策略 (DatabaseRejectionHandler)实现RejectedExecutionHandler接口当内存队列满时将任务存入数据库任务存入后会被后续的take()方法加载执行public class DatabaseRejectionHandler implements RejectedExecutionHandler { private RunnableTaskService runnableTaskService; public DatabaseRejectionHandler(RunnableTaskService runnableTaskService){ this.runnableTaskService runnableTaskService; } Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { SerializableTask serializableTask (SerializableTask) r; String s CustomTask.serializedTask(serializableTask); RunnableTask build RunnableTask.builder() .taskName(s) .taskState(0) .build(); int i runnableTaskService.saveRunnableTask(build); System.out.println(保存到数据库中: i); } }资源管理核心/最大线程数根据容器资源动态调整线程工厂添加命名前缀便于监控保活时间控制闲置线程销毁// 5. 监控线程池状态 ScheduledExecutorService monitor Executors.newSingleThreadScheduledExecutor(); monitor.scheduleAtFixedRate(() - { System.out.println(\n[监控] 活跃线程: executor.getActiveCount() | 队列大小: executor.getQueue().size() | 总完成任务: executor.getCompletedTaskCount()); }, 1, 2, TimeUnit.SECONDS);自定义线程工厂// 自定义线程工厂 static class NamedThreadFactory implements ThreadFactory { private final AtomicInteger counter new AtomicInteger(1); private final String namePrefix; public NamedThreadFactory(String namePrefix) { this.namePrefix namePrefix; } Override public Thread newThread(Runnable r) { return new Thread(r, namePrefix - counter.getAndIncrement()); } }测试public class RunnableTaskServiceImpl implements RunnableTaskService { // 任务队列用于存储待处理的任务 private final QueueRunnableTask localQueue new LinkedList(); private AtomicInteger count new AtomicInteger(); public int count(){ return count.get(); } /** * 保存可运行任务到队列 * * param runnableTask 待保存的任务对象 * throws IllegalArgumentException 如果任务对象为null */ Override public void saveRunnableTask(RunnableTask runnableTask) { // NPE检查验证任务对象不为空 if (runnableTask null) { return; } // 将任务添加到队列中 localQueue.add(runnableTask); count.incrementAndGet(); } /** * 从队列中加载并移除一个任务 * * return 队列中的第一个任务如果队列为空则返回null */ Override public RunnableTask loadTask() { // 从队列头部取出任务如果队列为空poll()会返回null RunnableTask runnableTask localQueue.poll(); // 可以根据业务需求添加日志 if (runnableTask null) { System.out.println([警告] 队列中没有可加载的任务); } count.decrementAndGet(); return runnableTask; } /** * 处理所有任务的主流程 * 创建线程池并提交任务进行并发执行 */ Override public void handlerAllTask() { ThreadPoolExecutor threadPoolExecutor null; try { // 步骤1初始化自定义阻塞队列 // 队列容量为10当队列满时会触发自定义的处理逻辑 CustomBlockQueue customBlockQueue new CustomBlockQueue(10, this); // 步骤2初始化数据库拒绝策略处理器 // 当线程池和队列都满时使用此处理器将任务持久化到数据库 DatabaseRejectionHandler databaseRejectionHandler new DatabaseRejectionHandler(this); // 步骤3创建线程池 // 核心线程数4最大线程数4空闲线程存活时间0秒 // 使用自定义阻塞队列和拒绝策略 threadPoolExecutor new ThreadPoolExecutor( 4, // 核心线程数 4, // 最大线程数 0, // 空闲线程存活时间 TimeUnit.SECONDS, // 时间单位 customBlockQueue, // 工作队列 databaseRejectionHandler // 拒绝策略 ); // NPE检查确保线程池创建成功 Objects.requireNonNull(threadPoolExecutor, 线程池创建失败); // 步骤4批量提交任务 int totalTasks 50; System.out.println(开始提交任务, 总数: totalTasks); // 循环创建并提交任务 for (int i 1; i totalTasks; i) { final int taskId i; // 创建可序列化的任务对象 SerializableTask serializableTask () - { // 打印当前执行任务的线程名称和任务ID System.out.println(Thread.currentThread().getName() 执行任务: taskId); }; // 提交任务到线程池执行 try { threadPoolExecutor.execute(serializableTask); } catch (Exception e) { // 捕获任务提交时的异常如线程池已关闭 System.err.println(任务 taskId 提交失败: e.getMessage()); e.printStackTrace(); } } System.out.println(所有任务已提交完成); // 步骤5优雅关闭线程池可选 // 注意根据业务需求决定是否需要等待任务完成 // threadPoolExecutor.shutdown(); // if (!threadPoolExecutor.awaitTermination(60, TimeUnit.SECONDS)) { // threadPoolExecutor.shutdownNow(); // } } catch (Exception e) { // 捕获整个流程中的异常确保程序不会崩溃 System.err.println(任务处理流程发生异常: e.getMessage()); e.printStackTrace(); // 如果线程池已创建尝试关闭 if (threadPoolExecutor ! null) { try { threadPoolExecutor.shutdownNow(); } catch (Exception shutdownException) { System.err.println(线程池关闭失败: shutdownException.getMessage()); } } } // 注释说明监控线程池状态的代码已注释 // 可以使用ScheduledExecutorService定期监控线程池的运行状态 // 包括活跃线程数、队列大小、已完成任务数等指标 } }

相关新闻

UE5中解决TopDown角色移动无动画问题:ABP_Manny适配指南

UE5中解决TopDown角色移动无动画问题:ABP_Manny适配指南

1. 项目概述:当ABP_Manny“罢工”时在虚幻引擎(UE)的TopDown(俯视角)项目模板里折腾过一阵子的朋友,估计都遇到过这个让人挠头的问题:你照着官方示例,把那个帅气的第三人称角色蓝图B…

2026/8/2 20:16:51 阅读更多 →
Unity游戏资源提取实战:AssetStudio核心原理与逆向工程应用

Unity游戏资源提取实战:AssetStudio核心原理与逆向工程应用

1. 项目概述:为什么我们需要提取Unity游戏资源?在游戏开发、逆向学习或者内容创作的过程中,你很可能遇到过这样的场景:看到一个Unity引擎制作的精美游戏,对其中的某个模型、一段音效或者一套UI界面爱不释手&#xff0c…

2026/8/2 20:15:51 阅读更多 →
如何快速上手Magpie:3分钟实现文本自动分类的完整指南

如何快速上手Magpie:3分钟实现文本自动分类的完整指南

如何快速上手Magpie:3分钟实现文本自动分类的完整指南 【免费下载链接】magpie Deep neural network framework for multi-label text classification 项目地址: https://gitcode.com/gh_mirrors/magp/magpie Magpie是一款专为多标签文本分类设计的深度神经网…

2026/8/2 20:15:51 阅读更多 →

最新新闻

构建可靠消息系统:使用AMQP库实现Elixir消费者GenServer的完整指南

构建可靠消息系统:使用AMQP库实现Elixir消费者GenServer的完整指南

构建可靠消息系统:使用AMQP库实现Elixir消费者GenServer的完整指南 【免费下载链接】amqp Idiomatic Elixir client for RabbitMQ 项目地址: https://gitcode.com/gh_mirrors/amqp1/amqp 在现代分布式系统中,可靠的消息传递是确保服务间通信稳定性…

2026/8/2 23:57:45 阅读更多 →
机械制图尺寸标注核心要素与实战技巧:从国标规范到CAD应用

机械制图尺寸标注核心要素与实战技巧:从国标规范到CAD应用

1. 从“看图说话”到“按图施工”:尺寸标注为何是机械设计的生命线在机械设计、加工和装配的整个链条里,图纸是唯一的、法定的“共同语言”。而在这门语言中,尺寸标注,尤其是尺寸线和尺寸界线构成的标注系统,就是最核心…

2026/8/2 23:57:45 阅读更多 →
基于长上下文大模型的医疗AI对话系统:从Gemini 1.5到AMIE的架构解析

基于长上下文大模型的医疗AI对话系统:从Gemini 1.5到AMIE的架构解析

1. 项目概述:当AI医生能记住你的整个病史 最近在医疗AI圈子里,一个来自谷歌DeepMind团队的项目“AMIE”引起了不小的震动。这个全称是“Articulate Medical Intelligence Explorer”的对话式医疗研究系统,在最近的一项评估中表现出了令人印象…

2026/8/2 23:57:45 阅读更多 →
机械制图尺寸标注实战:从设计意图到生产落地的核心技能

机械制图尺寸标注实战:从设计意图到生产落地的核心技能

1. 项目概述:从“看图说话”到“按图施工”的桥梁干了十几年机械设计,我越来越觉得,一张合格的工程图,其灵魂不在于画了多少条漂亮的线条,而在于尺寸标注是否清晰、准确、无歧义。新手设计师最容易犯的错,往…

2026/8/2 23:57:45 阅读更多 →
告别卡顿!gina.vim异步执行Git命令的核心原理与优势解析

告别卡顿!gina.vim异步执行Git命令的核心原理与优势解析

告别卡顿!gina.vim异步执行Git命令的核心原理与优势解析 【免费下载链接】vim-gina 👣 Asynchronously control git repositories in Neovim/Vim 8 项目地址: https://gitcode.com/gh_mirrors/vi/vim-gina gina.vim(gina)是…

2026/8/2 23:57:45 阅读更多 →
如何快速免费下载国家中小学智慧教育平台电子课本PDF文件

如何快速免费下载国家中小学智慧教育平台电子课本PDF文件

如何快速免费下载国家中小学智慧教育平台电子课本PDF文件 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课本内容。 项目地址: https:…

2026/8/2 23:56:45 阅读更多 →

日新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/2 6:34:16 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/2 2:47:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/2 0:23:22 阅读更多 →