Java 中基于优先级执行任务的线程池实现

在日常开发中,我们经常遇到这样一种需求:需要按照任务的优先级顺序来执行,而不是简单的先进先出(FIFO)。Java 提供了 PriorityBlockingQueue,这是一个基于优先级排序的线程安全队列,可以用于实现一个支持优先级任务的线程池。在这篇博客中,我们将介绍两种使用 PriorityBlockingQueue 实现优先级线程池的方法,并讨论它们的适用场景和优缺点。

方法一:实现 Comparable 接口的优先级任务类

1.1 方案概述

这种方法的核心在于让任务类(Task)实现 Comparable 接口,并在 compareTo 方法中定义优先级的排序逻辑。PriorityBlockingQueue 会根据 Comparable 的实现来自动对任务进行排序,优先级高的任务会被排在队列的前面,先执行。

1.2 实现步骤

  1. 定义优先级任务类:实现 RunnableCallable 接口,同时实现 Comparable 接口。
  2. 创建优先级线程池:使用 PriorityBlockingQueue 作为任务队列。
  3. 提交任务到线程池:按不同优先级提交任务,线程池会自动按照优先级来执行任务。

1.3 示例代码

import java.util.concurrent.*;public class PriorityTask implements Runnable, Comparable<PriorityTask> {private final int priority;private final String name;public PriorityTask(int priority, String name) {this.priority = priority;this.name = name;}@Overridepublic void run() {System.out.println("Executing task: " + name + " with priority: " + priority);}@Overridepublic int compareTo(PriorityTask other) {return Integer.compare(this.priority, other.priority); // 优先级值越小,优先级越高}
}public class PriorityThreadPoolExecutor extends ThreadPoolExecutor {public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new PriorityBlockingQueue<Runnable>());}
}

1.4 使用示例

public class Main {public static void main(String[] args) {PriorityThreadPoolExecutor executor = new PriorityThreadPoolExecutor(2, 4, 1, TimeUnit.MINUTES);executor.execute(new PriorityTask(10, "Low priority task"));executor.execute(new PriorityTask(1, "High priority task"));executor.execute(new PriorityTask(5, "Medium priority task"));executor.shutdown();}
}

1.5 优缺点

  • 优点

    • 直接在任务类中定义优先级逻辑,代码结构简单明了。
    • 无需额外的排序定义,PriorityBlockingQueue 自动根据 Comparable 实现排序。
  • 缺点

    • 任务类必须实现 Comparable 接口,优先级规则是硬编码在任务类中的,难以灵活修改。
    • 如果需要多种优先级规则,任务类代码会变得复杂,不适合多变的业务需求。

方法二:使用 Comparator 自定义排序规则

2.1 方案概述

在这种方法中,我们不再让任务类实现 Comparable 接口,而是使用 PriorityBlockingQueue 的构造方法传入一个 Comparator 对象。这样可以通过 Comparator 动态地定义任务的优先级排序规则。这种方式更加灵活,适合需要动态设置优先级或多重排序规则的场景。

2.2 实现步骤

  1. 定义任务类:实现 RunnableCallable 接口,无需实现 Comparable
  2. 创建优先级线程池:使用 PriorityBlockingQueue 作为任务队列,并传入自定义的 Comparator
  3. 提交任务到线程池:按照不同优先级提交任务,线程池会根据 Comparator 的排序规则来执行任务。

2.3 示例代码

import java.util.concurrent.*;public class Task implements Runnable {private final int priority;private final String name;public Task(int priority, String name) {this.priority = priority;this.name = name;}@Overridepublic void run() {System.out.println("Executing task: " + name + " with priority: " + priority);}public int getPriority() {return priority;}
}public class PriorityThreadPoolExecutor extends ThreadPoolExecutor {public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit,new PriorityBlockingQueue<>(11, Comparator.comparingInt(Task::getPriority)));}
}

2.4 使用示例

public class Main {public static void main(String[] args) {PriorityThreadPoolExecutor executor = new PriorityThreadPoolExecutor(2, 4, 1, TimeUnit.MINUTES);executor.execute(new Task(10, "Low priority task"));executor.execute(new Task(1, "High priority task"));executor.execute(new Task(5, "Medium priority task"));executor.shutdown();}
}

2.5 优缺点

  • 优点

    • 可以灵活定义优先级规则,通过传入不同的 Comparator 实现动态排序。
    • 更加清晰的结构,不需要在任务类中嵌入优先级排序逻辑,任务类更加独立。
  • 缺点

    • 相对复杂一些,需要定义额外的 Comparator
    • 可能需要管理多个 Comparator 实现,如果优先级规则过多,可能会增加一定的代码复杂度。

两种方法对比总结

比较项方法一:实现 Comparable方法二:使用 Comparator 自定义排序规则
代码结构任务类中包含优先级逻辑任务类和优先级规则分离
灵活性不灵活,排序规则固定灵活,可随时更改 Comparator
适用场景固定优先级规则动态优先级需求,多种排序规则
实现难度简单,适合初学者略复杂,需要理解 Comparator 使用
扩展性差,需改动任务类本身高,可复用不同 Comparator

总结

  • 如果您的任务优先级是固定的,而且排序规则简单,方法一:实现 Comparable 接口 更加直接明了。
  • 如果您需要灵活的优先级规则,或者希望在不同条件下使用不同的优先级排序规则,那么方法二:使用 Comparator 自定义排序规则更适合。

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

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

相关文章

Axure设计之三级联动选择器教程(中继器)

使用Axure设计三级联动选择器&#xff08;如省市区选择器&#xff09;时&#xff0c;可以利用中继器的数据存储和动态交互功能来实现。下面介绍中继器三级联动选择器设计的教程&#xff1a; 一、效果展示&#xff1a; 1、在三级联动选择器中&#xff0c;首先选择省份&#xff…

使用Docker-Compose安装redis,rabbitmq,nacos,mysql,nginx,tomcat,portainer组件教程

因为开发经常会用到一些组件&#xff0c;又不想在本地启动&#xff0c;所以买了个服务器&#xff0c;然后将这些组件都安装到服务器上以便开发使用。下面就记录下使用docker-compose安装组件的教程以及一些需要注意的地方。 关于docker和docker-compose的安装在另一篇博客中有…

安装PyG

PyG安装 官方链接 Installation — pytorch_geometric documentation (pytorch-geometric.readthedocs.io) 安装步骤&#xff1a; 步骤一&#xff1a;安装Anaconda和CUDA 安装Anaconda-CSDN博客安装CUDA-CSDN博客 步骤二&#xff1a;查看支持的Python版本 步骤三&#xf…

如何在Linux中使用Cron定时执行SQL任务

文章目录 前言一、方案分析二、使用步骤1.准备脚本2.crontab脚本执行 踩坑 前言 演示数据需要每天更新监控数据&#xff0c;不想手动执行&#xff0c;想到以下解决方案 navicat 创建定时任务java服务定时执行linux crontab 定时执行sql脚本 一、方案分析 我选择了第三个方案…

夜天之书 #103 开源嘉年华纪实

上周在北京参与了开源社主办的 2024 中国开源年会。其实相比于有点明显班味的“年会”&#xff0c;我的参会体验更像是经历了一场中国开源的年度嘉年华。这也是在会场和其他参会朋友交流时共同的体验&#xff1a;在开源社的 COSCon 活动上&#xff0c;能够最大限度地一次性见到…

Android Handler

Handler用于多线程消息分发和处理。与handler相关的几个对象&#xff1a;Message, Looper&#xff0c;MessageQueue, ThreadLocal. Handler是Message的消费者。 MessageQueue是容器。 Looper是整个Message分发的驱动。 Handler中有多种发送消息的方法&#xff0c;其中postxx…

C语言操作符详解(下)

⽬录 1. 单⽬操作符 2. 逗号表达式 3. 下标访问[]、函数调⽤() 4. 结构成员访问操作符 5. 操作符的属性&#xff1a;优先级、结合性 6. 表达式求值 一 单⽬操作符 1 分类 &#xff01;、 、 -- 、 & 、 * 、 、 - 、 ~ 、 sizeof 、 ( 类型 ) 1.1 "&q…

【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!

数据集介绍 【数据集】道路事故识别数据集 8939 张&#xff0c;目标检测&#xff0c;包含YOLO/VOC格式标注。数据集中包含2种分类&#xff1a;{0: accident, 1: non-accident}。数据集来自国内外图片网站和视频截图。检测范围道路事故检测、监控视角检测、无人机视角检测、等&…

跑批为什么这么难

业务系统产生的明细数据通常要经过加工处理&#xff0c;按照一定逻辑计算成需要的结果&#xff0c;用以支持企业的经营活动。这类数据加工任务一般会有很多个&#xff0c;需要批量完成计算&#xff0c;在银行和保险行业常常被称为跑批&#xff0c;其它像石油、电力等行业也经常…

A012-基于Spring Boot的私房菜定制上门服务系统的设计与实现

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统私房菜定制上门服务系统信息管理难度大&#xff0c;容错率…

配有生物振膜的FPS电竞耳机,血手幽灵M760,精准定位每一声脚步

在PC上玩游戏的时候&#xff0c;一款高性能的游戏耳机是提升游戏体验的关键&#xff0c;特别是在吃鸡等FPS类游戏中&#xff0c;耳机不仅是听觉享受的工具&#xff0c;更是决定胜负的关键装备。如果耳机的环绕立体声效果能够及时准确的做出反应&#xff0c;我在游戏中就能清晰地…

OceanBase详解及如何通过MySQL的lib库进行连接

OceanBase详解及如何通过MySQL的lib库进行连接 一、引言二、OceanBase概述1. 起源与发展2. 核心技术特点3. 应用场景三、OceanBase架构解析1. 系统架构2. 存储引擎3. 分布式架构四、如何使用MySQL的lib库连接OceanBase1. 前提条件2. 安装MySQL Connector/C3. 编写连接代码4. 编…

GPT原理;ChatGPT 等类似的问答系统工作流程如下;当用户向 ChatGPT 输入一个问题后:举例说明;ChatGPT不是通过索引搜索的传统知识库

目录 GPT原理 GPT架构 GPT 主要基于 Transformer 的解码器部分 ChatGPT 等类似的问答系统工作流程如下: 用户输入 文本预处理 模型处理 答案生成 输出回答 当用户向 ChatGPT 输入一个问题后:举例说明 文本预处理: ChatGPT不是通过索引搜索的传统知识库 GPT GPT…

【系统设计——认证授权——基本概念知识】

1. 认证和授权的区别 Authentication&#xff08;认证&#xff09; 是验证您的身份的凭据&#xff08;例如用户名/用户 ID 和密码&#xff09;&#xff0c;通过这个凭据&#xff0c;系统得以知道你就是你&#xff0c;也就是说系统存在你这个用户。所以&#xff0c;Authenticat…

Java:数据结构-再谈String类

字符串常量池 首先我们来思考这段代码&#xff0c;为什么运行结果一个是true&#xff0c;一个是false呢&#xff1f; public class Test {public static void main(String[] args) {String s1"123";String s2"123";String s3new String("555")…

centos7,yum安装mongodb

yum安装mongodb 1.配置MongoDB的yum源2.安装Mongodb3.启动Mongodb4.配置远程访问5.设置mongo密码 1.配置MongoDB的yum源 1.创建yum源文件&#xff0c;输入命令&#xff1a; vim /etc/yum.repos.d/mongodb-org-5.0.repo然后在文件中输入以下内容并保存&#xff1a; [mongodb-…

关于软测面试的20个终极问题,春招软测人快来看..

1. 项目测试流程你是怎么开展的&#xff1f; 【参考回答】 首先&#xff0c;需求分析阶段&#xff0c;主要参与需求评审会议&#xff0c;阅读理解业务需求&#xff0c;分析需求点。 需求确定后&#xff0c;进入测试计划阶段&#xff0c;参考软件需求规格说明书及项目总体计划…

风华高科签约实在RPA,引领粤港澳大湾区制造业数字化腾飞

近日&#xff0c;制造业单项冠军 “广东风华高新科技股份有限公司”&#xff08;以下简称 “风华高科”&#xff0c;股票代码&#xff1a;000636.SZ)与实在智能达成合作。 为贯彻落实党中央、国务院决策部署和国务院国资委《国有企业数字化转型行动计划》要求&#xff0c;培育…

Unity中IK动画与布偶死亡动画切换的实现

在Unity游戏开发中&#xff0c;Inverse Kinematics&#xff08;IK&#xff09;是创建逼真角色动画的强大工具。同时&#xff0c;能够在适当的时候切换到布偶物理状态来实现死亡动画等效果&#xff0c;可以极大地增强游戏的视觉体验。本文将详细介绍如何在Unity中利用IK实现常规…

【MongoDB】MongoDB的Java API及Spring集成(Spring Data)

文章目录 Java APISpring 集成1. 添加依赖2. 配置 MongoDB3. 创建实体类4. 创建 Repository 接口5. 创建 Service 类6. 创建 Controller 类7. 启动 Spring Boot 应用8. 测试你的 API 更多相关内容可查看 Java API maven <dependency><groupId>org.mongodb</gr…