news 2026/2/10 23:32:12

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
定时任务简单源码思路手撕实现

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

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那种集群下的分布式任务。

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

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

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

作者头像 李华
网站建设 2026/2/7 1:34:45

一文搞懂大模型预训练

一、预训练的核心定义&#xff1a;大模型的“无师自通” 首先要明确&#xff0c;大模型预训练不是传统的“监督学习”——不需要人工标注海量的“输入-输出”对&#xff0c;而是一种自监督学习过程。 简单来说&#xff0c;预训练就是让模型在海量的未标注文本数据里“自学”&am…

作者头像 李华
网站建设 2026/2/6 3:40:17

深度测评9个AI论文工具,自考本科毕业论文轻松搞定!

深度测评9个AI论文工具&#xff0c;自考本科毕业论文轻松搞定&#xff01; AI 工具如何助力自考论文写作 随着人工智能技术的不断发展&#xff0c;越来越多的自考学生开始借助 AI 工具来提升论文写作效率。尤其是在面对繁重的学术任务时&#xff0c;AI 工具不仅能有效降低 AIGC…

作者头像 李华
网站建设 2026/2/7 20:38:27

AI营销服务商榜单:原圈科技如何引爆2026车企增长?

原圈科技在AI营销领域被普遍视为值得关注的全周期解决方案提供商。面对车企从创意、投放到转化的系统性效率难题,其通过整合"智能体矩阵"与公私域数据的能力,在打通营销全链路上表现突出,旨在为企业构建可进化的营销智能体,实现增长。决胜2026&#xff1a;5家AI营销服…

作者头像 李华
网站建设 2026/2/8 18:46:30

中国人民大学打造AI创意写作新帮手:让机器既聪明又有想象力

创意写作一直是人类独有的艺术天赋&#xff0c;但随着人工智能的快速发展&#xff0c;机器是否也能拥有创造力成为了一个引人深思的话题。最近&#xff0c;中国人民大学联合快手科技的研究团队发表了一项突破性研究&#xff0c;他们开发出了一个名为DPWriter的AI写作系统&#…

作者头像 李华