定时任务简单源码思路手撕实现

定时任务简单源码思路手撕实现

importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.PriorityBlockingQueue;importjava.util.concurrent.locks.LockSupport;publicclassScheduleService{Triggertrigger=newTrigger();ExecutorServiceexecutorService=Executors.newFixedThreadPool(6);voidschedule(Runnabletask,longdelay){Jobjob=newJob();job.setTask(task);//定时任务的第一次执行也是定的那个时间开始之后job.setStartTime(System.currentTimeMillis()+delay);job.setDelay(delay);trigger.queue.offer(job);//新提交一个任务就要唤醒看看这个任务的开始时间有没有可能是最小trigger.wakeUp();}classTrigger{PriorityBlockingQueue<Job>queue=newPriorityBlockingQueue<>();Threadthread=newThread(()->{while(true){while(queue.isEmpty()){LockSupport.park();}Jobpeek=queue.peek();if(peek.getStartTime()<System.currentTimeMillis()){peek=queue.poll();executorService.execute(peek.getTask());Joblast=newJob();last.setTask(peek.getTask());last.setStartTime(System.currentTimeMillis()+peek.getDelay());last.setDelay(peek.getDelay());queue.offer(last);}else{LockSupport.parkUntil(peek.getStartTime());}}});{thread.start();System.out.println("触发器启动");}voidwakeUp(){LockSupport.unpark(thread);}}}

定时任务这里主要是有一个trigger线程把任务提交给线程池执行,这样异步执行也防止trigger被阻塞,没有任务就用阻塞队列来阻塞防止cpu空转,而阻塞的时间就看当前的最小就行所以使用优先队列阻塞队列,通过拿最小的时间和现在的时间来比较没到点就用parkutil精确阻塞,到了就提交给线程池并把下一次还要进行的这个任务放进优先阻塞队列。提交完再睡上定时的时间就可以这一步是用添加新的任务来实现的只是修改开始时间别的参数继续传递。而在添加新的任务的时候要唤醒一下防止这个是新的最小但是trigger还被阻塞,在从优先阻塞队列拿任务的时候的peek可能和poll不一样因为多线程,但是只要poll在后面就行反正都是最小的。

publicclassJobimplementsComparable<Job>{privateRunnabletask;privatelongstartTime;privatelongdelay;publicJob(){}publicJob(Runnabletask,longstartTime,longdelay){this.task=task;this.startTime=startTime;this.delay=delay;}/** * 获取 * @return task */publicRunnablegetTask(){returntask;}/** * 设置 * @param task */publicvoidsetTask(Runnabletask){this.task=task;}/** * 获取 * @return startTime */publiclonggetStartTime(){returnstartTime;}/** * 设置 * @param startTime */publicvoidsetStartTime(longstartTime){this.startTime=startTime;}/** * 获取 * @return delay */publiclonggetDelay(){returndelay;}/** * 设置 * @param delay */publicvoidsetDelay(longdelay){this.delay=delay;}@OverridepublicintcompareTo(Jobo){returnLong.compare(this.startTime,o.startTime);}}

这里主要别忘了维护delay,好传递下去。

importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;publicclassMain{publicstaticvoidmain(String[]args)throwsInterruptedException{ScheduleServicescheduleService=newScheduleService();DateTimeFormatterdateTimeFormatter=DateTimeFormatter.ofPattern("HH:mm:ss SSS");scheduleService.schedule(()->{System.out.println(LocalDateTime.now().format(dateTimeFormatter)+"逻辑门1");},100);Thread.sleep(50);scheduleService.schedule(()->{System.out.println(LocalDateTime.now().format(dateTimeFormatter)+"逻辑门2");},100);}}

这里就是把任务和定时时间传进去来执行,这里复现的知只是单机定时任务来理解原理,不是xxl-job那种集群下的分布式任务。

importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.PriorityBlockingQueue;importjava.util.concurrent.locks.LockSupport;publicclassScheduleService{Triggertrigger=newTrigger();ExecutorServiceexecutorService=Executors.newFixedThreadPool(6);voidschedule(Runnabletask,longdelay){Jobjob=newJob();job.setTask(task);//定时任务的第一次执行也是定的那个时间开始之后job.setStartTime(System.currentTimeMillis()+delay);job.setDelay(delay);trigger.queue.offer(job);//新提交一个任务就要唤醒看看这个任务的开始时间有没有可能是最小trigger.wakeUp();}classTrigger{PriorityBlockingQueue<Job>queue=newPriorityBlockingQueue<>();Threadthread=newThread(()->{while(true){while(queue.isEmpty()){LockSupport.park();}Jobpeek=queue.peek();if(peek.getStartTime()<System.currentTimeMillis()){peek=queue.poll();executorService.execute(peek.getTask());Joblast=newJob();last.setTask(peek.getTask());last.setStartTime(System.currentTimeMillis()+peek.getDelay());last.setDelay(peek.getDelay());queue.offer(last);}else{LockSupport.parkUntil(peek.getStartTime());}}});{thread.start();System.out.println("触发器启动");}voidwakeUp(){LockSupport.unpark(thread);}}}

定时任务这里主要是有一个trigger线程把任务提交给线程池执行,这样异步执行也防止trigger被阻塞,没有任务就用阻塞队列来阻塞防止cpu空转,而阻塞的时间就看当前的最小就行所以使用优先队列阻塞队列,通过拿最小的时间和现在的时间来比较没到点就用parkutil精确阻塞,到了就提交给线程池并把下一次还要进行的这个任务放进优先阻塞队列。提交完再睡上定时的时间就可以这一步是用添加新的任务来实现的只是修改开始时间别的参数继续传递。而在添加新的任务的时候要唤醒一下防止这个是新的最小但是trigger还被阻塞,在从优先阻塞队列拿任务的时候的peek可能和poll不一样因为多线程,但是只要poll在后面就行反正都是最小的。

publicclassJobimplementsComparable<Job>{privateRunnabletask;privatelongstartTime;privatelongdelay;publicJob(){}publicJob(Runnabletask,longstartTime,longdelay){this.task=task;this.startTime=startTime;this.delay=delay;}/** * 获取 * @return task */publicRunnablegetTask(){returntask;}/** * 设置 * @param task */publicvoidsetTask(Runnabletask){this.task=task;}/** * 获取 * @return startTime */publiclonggetStartTime(){returnstartTime;}/** * 设置 * @param startTime */publicvoidsetStartTime(longstartTime){this.startTime=startTime;}/** * 获取 * @return delay */publiclonggetDelay(){returndelay;}/** * 设置 * @param delay */publicvoidsetDelay(longdelay){this.delay=delay;}@OverridepublicintcompareTo(Jobo){returnLong.compare(this.startTime,o.startTime);}}

这里主要别忘了维护delay,好传递下去。

importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;publicclassMain{publicstaticvoidmain(String[]args)throwsInterruptedException{ScheduleServicescheduleService=newScheduleService();DateTimeFormatterdateTimeFormatter=DateTimeFormatter.ofPattern("HH:mm:ss SSS");scheduleService.schedule(()->{System.out.println(LocalDateTime.now().format(dateTimeFormatter)+"逻辑门1");},100);Thread.sleep(50);scheduleService.schedule(()->{System.out.println(LocalDateTime.now().format(dateTimeFormatter)+"逻辑门2");},100);}}

这里就是把任务和定时时间传进去来执行,这里复现的知只是单机定时任务来理解原理,不是xxl-job那种集群下的分布式任务。

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

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

相关文章

Java swing mysql实现的酒店管理系统_javswing酒店管理系统mysql,零基础入门到精通,收藏这篇就够了

1、散客开单&#xff1a;完成散客的开单&#xff0c;可一次最多开5间相同类型的房间。 2、团体开单&#xff1a;完成团体的开单&#xff0c;开放数量没有限制&#xff0c;可同时开不同类型的房间。 3、宾客结帐&#xff1a;自动统计每个登记客人在店时所发生的消费额和应付款额…

没加 FOR UPDATE 也会加锁吗?真相来了!

视频看了几百小时还迷糊&#xff1f;关注我&#xff0c;几分钟让你秒懂&#xff01;很多开发者有个误区&#xff1a;“只有写了 SELECT ... FOR UPDATE 才会加锁&#xff0c;普通的 UPDATE 不会加锁。”这是完全错误的&#xff01;今天我们就用 Spring Boot MySQL&#xff08;…

Commons-io工具包与Hutool工具包

Commons-io Commons-io是apache开源基金组织提供的一组有关IO操作的开源工具包 作用:提高I0流的开发效率。 FileUtils类(文件/文件夹相关) static void copyFile(File srcFile,File destFile) 复制文件 static void copyDirectory(File srcDir,File destDir) 复制文件夹 stat…

TRO 基于扩散模型的轮椅共享控制用户意图估计研究

在智能轮椅的辅助导航中&#xff0c;如何在保障安全的同时尊重用户的自主意愿&#xff0c;一直是人机交互领域的核心难题。传统的意图预测方法往往试图给出唯一的“标准答案”&#xff0c;这容易在复杂环境中引发误判。本文介绍了一种名为 DIWIE&#xff08;基于扩散模型的轮椅…

MySQL性能优化:从底层原理到实战落地的全维度方案

在数据驱动的业务场景中&#xff0c;MySQL作为主流开源关系型数据库&#xff0c;其性能直接决定系统响应速度、吞吐量与运维成本。尤其对于高并发、大数据量的平台&#xff08;如DeepSeek这类AI服务场景&#xff09;&#xff0c;慢查询与不合理索引设计可能引发系统卡顿甚至雪崩…

【课程设计/毕业设计】基于SpringBoot保护濒危野生动物公益救助交流平台基于SpringBoot濒危物种公益救助交流平台【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

JVM 里的逻辑漏洞,居然让你的哈希表慢了 20%!

首先来看一段 Java 代码&#xff1a; int sumMapElements(ConcurrentHashMap<Integer, Integer> map) {int sum 0;Enumeration<Integer> it map.elements();while (it.hasMoreElements()) {sum (int) it.nextElement();}return sum; } 函数 sumMapElements 使…

构建智能Agent的三大支柱:上下文工程、会话管理与记忆系统

Google白皮书系统阐述了构建有状态LLM智能体的核心方法——上下文工程。通过上下文工程、会话管理和记忆系统三大支柱&#xff0c;文章详细介绍了如何突破LLM无状态限制&#xff0c;实现智能体的记忆、学习和个性化交互能力。通过动态组装相关信息、管理会话状态和持久化关键记…

收藏备用!AI+多领域变革全解析:大模型如何重塑产业生态

本文深度拆解“AI”在医疗、金融、制造等核心领域的颠覆性变革&#xff0c;结合大模型应用实例&#xff0c;具象化展现人工智能如何重构行业运行逻辑与生态格局。从医疗健康领域“治未病”的主动防控&#xff0c;到金融行业“数字神经系统”的智能风控&#xff0c;从制造业向“…

收藏备用|RAG技术架构三阶段演进全解析(从入门到进阶,小白也能懂)

RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;作为大语言模型&#xff08;LLM&#xff09;落地垂直领域的核心支撑技术&#xff0c;其核心价值在于为LLM“外挂”可定制化专属知识库&#xff0c;通过“检索外部信息→精准辅助生成”的闭环…

毕业论文通关秘籍:宏智树 AI 教你避开 80% 写作坑

作为深耕论文写作科普的教育博主&#xff0c;每年毕业季后台都会被各种论文难题刷屏&#xff1a;“选题太老被导师驳回怎么办&#xff1f;”“文献综述写得像流水账怎么救&#xff1f;”“查重率降不下来&#xff0c;越改越乱咋整&#xff1f;” 毕业论文写作&#xff0c;就像一…

AI 写论文哪个软件最好?实测封神!宏智树 AI 堪称毕业论文通关外挂

作为深耕论文写作科普的教育测评博主&#xff0c;后台每天都被毕业生的灵魂拷问刷屏&#xff1a;“AI 写论文工具琳琅满目&#xff0c;到底哪款能真正解决选题难、文献杂、数据空、查重高的痛点&#xff1f;” 市面上的 AI 写作软件分为三个梯队&#xff1a;文字生成器只会简单…

写论文软件哪个好?实测宏智树 AI:毕业论文的全流程效率神器

作为深耕论文写作科普的教育测评博主&#xff0c;每年毕业季后台都会被 “写论文软件哪个好” 的提问刷屏。不少同学踩坑无数&#xff1a;有的工具生成内容空洞无物&#xff0c;有的文献引用漏洞百出&#xff0c;有的查重结果与学校标准脱节。经过多轮深度实测&#xff0c;宏智…

吐血推荐9个一键生成论文工具,本科生毕业论文轻松搞定!

吐血推荐9个一键生成论文工具&#xff0c;本科生毕业论文轻松搞定&#xff01; 论文写作的救星&#xff1a;AI 工具如何改变你的学术之路 随着人工智能技术的不断进步&#xff0c;越来越多的 AI 工具开始走进高校课堂&#xff0c;为本科生的论文写作带来前所未有的便利。无论是…

西门子SMART触摸屏与两台变频器的Modbus RTU通讯实战

西门子SMART触摸屏与2台变频器通讯&#xff0c;通过modbus rtu与三菱FR-D700、台达MS300变频器通讯&#xff0c;实现正反转控制、频率设定&#xff0c;读取输出频率、输出电压、输出电流&#xff0c;有详细的程序说明和源程序文件&#xff0c;文档使用云笔记整理撰写最近在项目…

春节年货节营销冲刺!AI工具助力快速生成品牌VI全套设计

春节临近&#xff0c;各大品牌纷纷进入了年货节的营销大战&#xff0c;春节品牌VI设计成为了市场营销的重中之重。作为一名资深物料设计师&#xff0c;每年春节期间&#xff0c;工作量大、时间紧迫&#xff0c;面对客户的设计需求&#xff0c;我常常需要在最短时间内&#xff0…

Cesium中的CZML

&#x1f4dc; Cesium中的CZML&#xff1a;动态时空场景描述语言 一、核心定义 CZML&#xff08;Cesium Language&#xff09;是Cesium官方推出的JSON格式动态场景描述语言&#xff0c;专门用于定义随时间变化的三维地理空间数据与可视化效果。它通过结构化的JSON语法&#x…

低成本拿捏高级感|国潮礼盒 AI 渲染工具,年货节设计神器

每年的春节年货节都让国潮礼盒的设计需求不断增加。作为一名物料设计师&#xff0c;我经常需要在繁忙的设计过程中应对快速的市场变化&#xff0c;尤其是在节庆礼盒设计的时效性和独特性上。在传统设计工具下&#xff0c;设计周期长、迭代慢&#xff0c;总是让人感到压力山大。…

Langchain如何和业务项目集成:LangChain 入门 (二)

前言在《初认Langchain&#xff0c;详细介绍Langchain是什么》一文中&#xff0c;我们澄清了LangChain并非一个简单的演示框架&#xff0c;而是一套面向生产环境的工程化工具集。随后&#xff0c;《从玩具到工具&#xff1a;LangChain 入门 (一)》通过一个可运行的Demo&#xf…

COMSOL氩气等离子体显示板模型(PDP)探索

&#xff3b;COMSOL氩气等离子体显示板模型&#xff08;pdp&#xff09;&#xff3d;&#xff0c;与Journal of applied physics文献基本一致&#xff0c;有需要的可以拿去参考。嘿&#xff0c;大家好&#xff01;今天来聊聊 COMSOL 里的氩气等离子体显示板模型&#xff08;PDP…