news 2026/5/12 9:36:45

使用 Java 实现一个简单且高效的任务调度框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Java 实现一个简单且高效的任务调度框架

使用 Java 实现一个简单且高效的任务调度框架(2026年实用版)

任务调度框架是后台系统中的核心组件,用于管理定时任务、延迟任务、周期任务等。Java 生态中已有 Quartz、Spring Task 等成熟框架,但如果你想从零实现一个简单、高效的版本(适合学习/小项目),可以基于java.util.concurrent包构建——它原生支持线程池、多线程调度,避免从头造轮子。

设计原则(保持简单高效):

  • 核心功能:支持一次性任务、固定延迟任务、固定频率任务、任务取消。
  • 高效点:使用ScheduledThreadPoolExecutor作为底层引擎(JDK内置,高性能,支持优先级队列)。
  • 简单点:最小接口设计,无外部依赖,仅需 JDK 8+。
  • 局限:不支持持久化/分布式(如果需要,可扩展到 Redis/Zookeeper),不处理异常重试(可加装饰器)。
  • 适用场景:小中型应用、原型开发、面试手写题。
总体架构(用表格表示,便于理解)
组件描述实现方式
Task任务接口(Runnable 扩展,支持优先级/元数据)自定义接口,包含 id/priority
TaskScheduler调度器接口(提交任务、调度任务、取消任务)核心类,使用 ScheduledExecutorService
PriorityQueue内部队列(支持优先级调度)PriorityBlockingQueue
ThreadPool执行引擎(线程复用,避免频繁创建线程)ScheduledThreadPoolExecutor
示例扩展可加日志、监控(e.g., JMX)、异常处理通过装饰器模式
核心代码实现(完整、可直接复制运行)
  1. 任务接口(SimpleTask.java)
    支持基本元数据,便于追踪/取消。

    importjava.util.UUID;publicinterfaceSimpleTaskextendsRunnable{StringgetId();// 唯一ID,用于取消intgetPriority();// 优先级(越小越高,默认0)}// 默认实现(方便用户继承)abstractclassAbstractSimpleTaskimplementsSimpleTask{privatefinalStringid=UUID.randomUUID().toString();privatefinalintpriority;publicAbstractSimpleTask(intpriority){this.priority=priority;}@OverridepublicStringgetId(){returnid;}@OverridepublicintgetPriority(){returnpriority;}}
  2. 调度器实现(SimpleTaskScheduler.java)
    核心类,封装 ScheduledExecutorService。

    importjava.util.concurrent.*;importjava.util.Map;importjava.util.HashMap;publicclassSimpleTaskScheduler{privatefinalScheduledExecutorServiceexecutor;privatefinalMap<String,ScheduledFuture<?>>taskMap=newHashMap<>();// 追踪任务,便于取消publicSimpleTaskScheduler(intcorePoolSize){executor=Executors.newScheduledThreadPool(corePoolSize);}// 提交一次性任务(立即执行)publicvoidsubmit(SimpleTasktask){executor.execute(task);}// 调度延迟任务(delay 后执行一次)publicvoidschedule(SimpleTasktask,longdelay,TimeUnitunit){ScheduledFuture<?>future=executor.schedule(task,delay,unit);taskMap.put(task.getId(),future);}// 调度固定频率任务(initialDelay 后,每 period 执行一次)publicvoidscheduleAtFixedRate(SimpleTasktask,longinitialDelay,longperiod,TimeUnitunit){ScheduledFuture<?>future=executor.scheduleAtFixedRate(task,initialDelay,period,unit);taskMap.put(task.getId(),future);}// 调度固定延迟任务(initialDelay 后,每次执行完后延迟 delay 执行下一次)publicvoidscheduleWithFixedDelay(SimpleTasktask,longinitialDelay,longdelay,TimeUnitunit){ScheduledFuture<?>future=executor.scheduleWithFixedDelay(task,initialDelay,delay,unit);taskMap.put(task.getId(),future);}// 取消任务publicbooleancancel(StringtaskId){ScheduledFuture<?>future=taskMap.remove(taskId);if(future!=null){returnfuture.cancel(false);// false: 不中断正在运行的任务}returnfalse;}// 优雅关闭调度器publicvoidshutdown(){executor.shutdown();try{if(!executor.awaitTermination(60,TimeUnit.SECONDS)){executor.shutdownNow();}}catch(InterruptedExceptione){executor.shutdownNow();}}}
  3. 示例使用(Main.java)
    测试各种调度场景。

    publicclassMain{publicstaticvoidmain(String[]args){SimpleTaskSchedulerscheduler=newSimpleTaskScheduler(4);// 4 核心线程// 一次性任务SimpleTaskoneTimeTask=newAbstractSimpleTask(0){@Overridepublicvoidrun(){System.out.println("一次性任务执行: "+System.currentTimeMillis());}};scheduler.submit(oneTimeTask);// 延迟任务(5秒后执行)SimpleTaskdelayedTask=newAbstractSimpleTask(1){@Overridepublicvoidrun(){System.out.println("延迟任务执行: "+System.currentTimeMillis());}};scheduler.schedule(delayedTask,5,TimeUnit.SECONDS);StringdelayedId=delayedTask.getId();// 保存ID,用于可能取消// 固定频率任务(立即开始,每2秒执行一次)SimpleTaskfixedRateTask=newAbstractSimpleTask(2){@Overridepublicvoidrun(){System.out.println("固定频率任务: "+System.currentTimeMillis());}};scheduler.scheduleAtFixedRate(fixedRateTask,0,2,TimeUnit.SECONDS);// 固定延迟任务(1秒后开始,每次执行完后延迟3秒)SimpleTaskfixedDelayTask=newAbstractSimpleTask(3){@Overridepublicvoidrun(){System.out.println("固定延迟任务开始: "+System.currentTimeMillis());try{Thread.sleep(1000);}catch(InterruptedExceptione){}// 模拟耗时1秒System.out.println("固定延迟任务结束: "+System.currentTimeMillis());}};scheduler.scheduleWithFixedDelay(fixedDelayTask,1,3,TimeUnit.SECONDS);// 模拟运行10秒后取消一个任务try{Thread.sleep(10000);}catch(InterruptedExceptione){}scheduler.cancel(delayedId);// 取消延迟任务(如果还没执行)// 关闭调度器scheduler.shutdown();}}
性能优化 & 扩展建议(高效点)

运行 Main.java,你会看到控制台输出各种任务的执行时间戳。简单吧?这个框架参数少、开销低(JDK 原生),实际项目中可作为起点扩展。

如果你想加特定功能(e.g., Cron 表达式支持、持久化),或遇到报错,告诉我,我可以给你更详细的代码调整~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/4 22:02:43

学长亲荐2026TOP9AI论文软件:本科生毕业论文全场景测评

学长亲荐2026TOP9AI论文软件&#xff1a;本科生毕业论文全场景测评 推荐1&#xff1a;「千笔AI」—— 一站式学术支持“专家”&#xff0c;学术写作全场景王者&#xff08;推荐指数&#xff1a;★★★★★&#xff09; 在众多AI论文工具中&#xff0c;「千笔AI」凭借其强大的功…

作者头像 李华
网站建设 2026/5/11 8:36:58

面向 OpenHarmony 的 Flutter UI 实践:便签卡片组件从设计到落地

文章目录面向 OpenHarmony 的 Flutter UI 实践&#xff1a;便签卡片组件从设计到落地前言背景Flutter OpenHarmony 跨端开发介绍架构定位开发核心代码便签卡片组件实现代码结构解析1. 状态驱动的颜色设计2. Card InkWell 的交互组合3. 顶部信息区&#xff1a;标题 完成状态4…

作者头像 李华
网站建设 2026/5/11 1:19:37

linux 如何查看udp协议缓冲区的默认大小

在 Linux 系统中&#xff0c;UDP 协议的接收和发送缓冲区大小可以通过内核参数进行配置。要查看 UDP 缓冲区的默认大小&#xff08;即未显式设置时的初始值&#xff09;以及最大限制&#xff0c;可以使用以下方法&#xff1a;1. 查看系统级别的 UDP 缓冲区默认值和限制这些值由…

作者头像 李华
网站建设 2026/5/6 20:08:57

【AI大模型开发】-基于FAISS的语义搜索系统(实战)

向量数据库实战&#xff1a;基于FAISS的语义搜索系统 一、项目概述 1.1 什么是向量数据库&#xff1f; 向量数据库是一种专门用于存储、索引和检索高维向量数据的数据库系统。在AI领域&#xff0c;向量通常是指通过预训练模型&#xff08;如Transformer&#xff09;将文本、图像…

作者头像 李华
网站建设 2026/5/10 14:24:13

老张的AI助手,每天早上帮他念一遍:“你不是机器。”

第一章&#xff1a;晨间仪式的技术隐喻 当老张的智能音箱第七次用合成语音念出“你不是机器”时&#xff0c;他正在调试金融系统的模糊测试脚本。这个看似荒诞的晨间仪式&#xff0c;恰是软件测试从业者的生存宣言——在自动化测试覆盖率突破80%的2026年&#xff0c;人类测试工…

作者头像 李华