三亚网页制作,网站排名网站优化,wordpress 显示一篇,wordpress多级菜单会变慢一、Quartz介绍 Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目#xff0c;完全由Java开发#xff0c;可以用来执行定时任务#xff0c;类似于java.util.Timer。但是相较于Timer#xff0c; Quartz增加了很多功能#xff1a; 1.持久性作业 … 一、Quartz介绍 Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目完全由Java开发可以用来执行定时任务类似于java.util.Timer。但是相较于Timer Quartz增加了很多功能 1.持久性作业 - 就是保持调度定时的状态; 2.作业管理 - 对调度作业进行有效的管理; Quartz是一个强大任务调度框架可以用来干嘛 简单来说就是实现“计划(或定时)任务”的系统例如 订单下单后未付款15分钟后自动撤消订单并自动解锁锁定的商品 一个OA系统需要在每周五9点自动生成数据报表 比如vip的每月自动续费功能 或者想每月10号自动还款 又或者每周给暗恋的女生定时发送邮件等等。 Java 语言实现定时任务的几种方式 java.util.Timer一个 JDK 中自带的处理简单定时任务的工具。 java.util.concurrent.ScheduledExecutorServiceJDK 中的定时任务接口可以将定时任务与线程池功能结合使用。 org.springframework.scheduling.annotation.ScheduledSpring 框架中基于注解来实现定时任务处理。 Quartz一个完全由 Java 语言编写的支持分布式调度任务的开源框架。 二、Quartz的核心概念 三大核心类 JObDetail作业类Trigger触发器Scheduler调度器。Trigger指定JObDetail什么时候发布任务。 1任务job job就是你想实现的任务类每一个job必须实现org.quartz.job接口且只需实现接口定义的execute()方法。 Job工作任务调度的接口任务类需要实现该接口该接口中定义execute方法类似jdk提供的TimeTask类的run方法在里面编写任务执行的业务逻辑。 Job:实例在Quartz中的生命周期每次调度器执行job时它在调用execute方法前会创建一个新的job实例当调用完成后关联的job对象实例会被是释放释放的实例会被垃圾回收机制回收。 2触发器Trigger Trigger 为你执行任务的触发器比如你想每天定时1点发送邮件Trigger将会设置1点执行该任务。 Trigger主要包含两种SimpleTrigger和CronTriggerr。 3调度器Scheduler Scheduler是任务的调度器会将任务job和触发器TRigger结合负责基于Trigger设定的时间执行job。 三、Quartz的几个常用API Scheduler 用于与调度程序交互的主程序接口。 Job :预先定义的希望在未来时间被调度程序执行的任务类自定义。 JobDetall 使用JobDetail来定义定时任务的实例JobDetail实例是通过JobBuilder类创建。 JobDataMap 可包含数据对象在job实例执行的是好可使用包含的数据JobDataMap是java Map接口的实现增加了一些存取基本类型方法。 Trgger触发器 Trigger对象是用于触发执行Job的当调度一个Job时我们实例一个触发器然后调整它的属性来满足Job执行的条件表明任务在什么时候执行。定义了一个已经被安排的任务将在什么时候执行的时间条件比如每秒执行一次。 JobBuilder 用于声明一个任务实例也可以定义关于该任务的详情比如任务名组名等这个声明的实例将作为一个实例执行的任务。 TriggerBuilder 触发器创建器用于创建触发器trigger实例。 JobListener,TriggerListener,SchedulerListener监听器用于对组件的监听。 四、Quartz的简单使用 运行程序可以看到程序每隔1s会打印出内容且在12s后程序结束。 创建项目并加入依赖参考【普通的IDEA maven java项目demohello word-1.8】待更新CSDN链接 dependency groupIdorg.quartz-scheduler/groupId artifactIdquartz/artifactId version2.3.2/version /dependency 新建一个能够打印任意内容的Job import org.quartz.Job; import org.quartz.JobExecutionContext; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; public class PrintWordsJob implements Job { Override public void execute(JobExecutionContext jobExecutionContext) { String printTime new SimpleDateFormat(yy-MM-dd HH-mm-ss:SSS).format(new Date()); System.out.println(PrintWordsJob start at: printTime , prints: Hello Job- new Random().nextInt(100)); } } 创建Schedule执行任务 import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; public class Demo { public static void main(String[] args) throws SchedulerException, InterruptedException { // 1、创建JobDetail实例并与PrintWordsJob类绑定(Job执行内容) JobDetail jobDetail JobBuilder.newJob(PrintWordsJob.class) .withIdentity(job1, group1).build(); // 2、构建Trigger实例,每隔1s执行一次 Trigger trigger TriggerBuilder.newTrigger().withIdentity(trigger1, triggerGroup1) .startNow()// 立即生效 .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(1)// 每隔1s执行一次 .repeatForever()).build();// 一直执行 // 3、创建调度器Scheduler并执行 Scheduler scheduler new StdSchedulerFactory().getScheduler(); scheduler.scheduleJob(jobDetail, trigger); System.out.println(--------scheduler start ! ------------); System.out.println(at: new SimpleDateFormat(yy-MM-dd HH-mm-ss:SSS).format(new Date()) , prints: Hello scheduler); scheduler.start(); // 睡眠12秒 TimeUnit.MILLISECONDS.sleep(12000); scheduler.shutdown(); System.out.println(at: new SimpleDateFormat(yy-MM-dd HH-mm-ss:SSS).format(new Date()) , prints: Hello scheduler); System.out.println(--------scheduler shutdown ! ------------); } } 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-22 00-05-01:123, prints: Hello scheduler PrintWordsJob start at:23-08-22 00-05-01:129, prints: Hello Job-69 PrintWordsJob start at:23-08-22 00-05-02:052, prints: Hello Job-68 PrintWordsJob start at:23-08-22 00-05-03:057, prints: Hello Job-93 PrintWordsJob start at:23-08-22 00-05-04:061, prints: Hello Job-32 PrintWordsJob start at:23-08-22 00-05-05:057, prints: Hello Job-14 PrintWordsJob start at:23-08-22 00-05-06:051, prints: Hello Job-55 PrintWordsJob start at:23-08-22 00-05-07:058, prints: Hello Job-30 PrintWordsJob start at:23-08-22 00-05-08:048, prints: Hello Job-82 PrintWordsJob start at:23-08-22 00-05-09:058, prints: Hello Job-28 PrintWordsJob start at:23-08-22 00-05-10:059, prints: Hello Job-97 PrintWordsJob start at:23-08-22 00-05-11:053, prints: Hello Job-88 PrintWordsJob start at:23-08-22 00-05-12:048, prints: Hello Job-18 PrintWordsJob start at:23-08-22 00-05-13:057, prints: Hello Job-93 at:23-08-22 00-05-13:135, prints: Hello scheduler --------scheduler shutdown ! ------------ 五、Quartz核心详解 1.Job和JobDetail Job是Quartz中的一个接口接口下只有execute方法在这个方法中编写业务逻辑。 JobDetail用来绑定Job为Job实例提供许多属性name、group、jobClass、jobDataMap JobDetail绑定指定的Job每次Scheduler调度执行一个Job的时候首先会拿到对应的Job然后创建该Job实例再去执行Job中的execute()的内容任务执行结束后关联的Job对象实例会被释放且会被JVM GC清除。 为什么设计成JobDetail Job不直接使用Job JobDetail定义的是任务数据而真正的执行逻辑是在Job中。 这是因为任务是有可能并发执行如果Scheduler直接使用Job就会存在对同一个Job实例并发访问的问题。而JobDetail Job 方式Sheduler每次执行都会根据JobDetail创建一个新的Job实例这样就可以规避并发访问的问题。 2.Trigger、SimpleTrigger、CronTrigger Trigger Trigger是Quartz的触发器会去通知Scheduler何时去执行对应Job。 new Trigger().startAt():表示触发器首次被触发的时间; new Trigger().endAt():表示触发器结束触发的时间; SimpleTrigger SimpleTrigger可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。 将下述代码替换上述【Quartz的简单使用】代码的 // 2、构建Trigger实例,每隔1s执行一次 内容 程序运行5s后开始执行Job执行Job 5s后再延时2s结束程序 // 2、构建Trigger实例,每隔1s执行一次 Date startDate new Date(); startDate.setTime(startDate.getTime() 5000); Date endDate new Date(); endDate.setTime(startDate.getTime() 5000); Trigger trigger TriggerBuilder.newTrigger().withIdentity(trigger1, triggerGroup1) .usingJobData(trigger1, 这是jobDetail1的trigger) .startNow()//立即生效 .startAt(startDate) .endAt(endDate) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(1)// 每隔1s执行一次 .repeatForever()).build();// 一直执行 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-22 00-08-34:658, prints: Hello scheduler PrintWordsJob start at:23-08-22 00-08-39:573, prints: Hello Job-81 PrintWordsJob start at:23-08-22 00-08-40:553, prints: Hello Job-63 PrintWordsJob start at:23-08-22 00-08-41:560, prints: Hello Job-87 PrintWordsJob start at:23-08-22 00-08-42:562, prints: Hello Job-25 PrintWordsJob start at:23-08-22 00-08-43:554, prints: Hello Job-65 at:23-08-22 00-08-46:666, prints: Hello scheduler --------scheduler shutdown ! ------------ CronTrigger CronTrigger功能非常强大是基于日历的作业调度而SimpleTrigger是精准指定间隔所以相比SimpleTriggerCroTrigger更加常用。CroTrigger是基于Cron表达式的了解Cron表达式可参考【cron表达式 详解】cron表达式 详解_linux cron表达式_西晋的no1的博客-CSDN博客 在线生成corn表达式 在线Cron表达式生成器 将下述代码替换上述【Quartz的简单使用】代码的 // 2、构建Trigger实例,每隔1s执行一次 内容 从0秒开始,每5秒执行一次定时任务 // 2.触发器 CronTrigger trigger TriggerBuilder.newTrigger().withIdentity(trigger, group).startNow()//立刻执行 .usingJobData(trigger1, 这是jobDetail1的trigger) .withSchedule(CronScheduleBuilder.cronSchedule(0/5 * * * * ? *))//表示每次0秒时候执行。 .build(); 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-22 00-21-35:870, prints: Hello scheduler PrintWordsJob start at:23-08-22 00-21-35:877, prints: Hello Job-39 PrintWordsJob start at:23-08-22 00-21-40:001, prints: Hello Job-68 PrintWordsJob start at:23-08-22 00-21-45:002, prints: Hello Job-8 at:23-08-22 00-21-47:873, prints: Hello scheduler --------scheduler shutdown ! ------------ 六、JobListener 创建MyJobListener实现JobListener接口 import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobListener; public class MyJobListener implements JobListener { public String getName() { return this.getClass().getSimpleName(); } //Scheduler在jobDetail将要被执行时调用这个方法执行前 public void jobToBeExecuted(JobExecutionContext context) { String jobName context.getJobDetail().getKey().getName(); System.out.println(我的job名1 jobName); } //Scheduler在jobDetail即将被执行但又被TriggerListermer 否定时会调用该方法 public void jobExecutionVetoed(JobExecutionContext context) { String jobName context.getJobDetail().getKey().getName(); System.out.println(我的job名2 jobName); } //Scheduler在jobDetail即将被执行之后调用这个方法。执行后 public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { String jobName context.getJobDetail().getKey().getName(); System.out.println(我的job名3 jobName); } } 在scheduler创建后加入监听即可生效 scheduler.getListenerManager().addJobListener(new MyJobListener()); 将下述蓝色代码放于上述【Quartz的简单使用】对应位置 // 3、创建调度器Scheduler并执行 Scheduler scheduler new StdSchedulerFactory().getScheduler(); scheduler.getListenerManager().addJobListener(new MyJobListener()); scheduler.scheduleJob(jobDetail, trigger); 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-22 00-28-12:174, prints: Hello scheduler 我的job名1job1 PrintWordsJob start at:23-08-22 00-28-12:179, prints: Hello Job-7 我的job名3job1 我的job名1job1 PrintWordsJob start at:23-08-22 00-28-13:112, prints: Hello Job-39 我的job名3job1 我的job名1job1 … … … PrintWordsJob start at:23-08-22 00-28-23:111, prints: Hello Job-0 我的job名3job1 我的job名1job1 PrintWordsJob start at:23-08-22 00-28-24:115, prints: Hello Job-12 我的job名3job1 at:23-08-22 00-28-24:179, prints: Hello scheduler --------scheduler shutdown ! ------------ 七、TriggerListener 任务调度过程中与触发器Trigger相关的事件包括触发器触发触发器未正常触发触发器完成等。 import org.quartz.JobExecutionContext; import org.quartz.Trigger; import org.quartz.TriggerListener; public class MyTriggerListener implements TriggerListener { //用于获取触发器的名称 public String getName() {//获取默认类名 return this.getClass().getSimpleName(); } //当与监听器相关联的trigger被触发job上的execute()方法将被执行时Scheduler就调用该方法 public void triggerFired(Trigger trigger, JobExecutionContext context) { System.out.println(triggerFired); } //在Trigger触发后job将要被执行时由Scheduler调用这个方法。 //TriggerListener给一个选择去否决job的执行。如方法返回truejob此次将不会为trigger触发执行。false放行。 public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) { System.out.println(vetoJobExecution); return false; } //Scheduler 调用这个方法是在trigger错过时触发。 public void triggerMisfired(Trigger trigger) { System.out.println(triggerMisfired); } //triggerCompletetrigger被触发并且完成了job的执行时Scheduler调用这个方法。 public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) { System.out.println(triggerComplete); } } 将下述蓝色代码放于上述【Quartz的简单使用】对应位置 // 3、创建调度器Scheduler并执行 Scheduler scheduler new StdSchedulerFactory().getScheduler(); scheduler.getListenerManager().addTriggerListener(new MyTriggerListener()); scheduler.scheduleJob(jobDetail, trigger); 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-22 00-34-56:592, prints: Hello scheduler triggerFired vetoJobExecution PrintWordsJob start at:23-08-22 00-34-56:601, prints: Hello Job-69 triggerComplete triggerFired vetoJobExecution … … … PrintWordsJob start at:23-08-22 00-35-07:530, prints: Hello Job-13 triggerComplete triggerFired vetoJobExecution PrintWordsJob start at:23-08-22 00-35-08:535, prints: Hello Job-21 triggerComplete at:23-08-22 00-35-08:597, prints: Hello scheduler --------scheduler shutdown ! ------------ 八、SchedulerListener SchedulerListener会在scheduler的生命周期中关键事件发生时被调用与Scheduler有关事件增加或者删除一个 job/trigger关闭scheduler等。 import org.quartz.*; public class MySchedulerListener implements SchedulerListener { //用于部署JobDetail 的时候调用 public void jobScheduled(Trigger trigger) { String name trigger.getKey().getName(); System.out.println(获取触发器名称 name); } //卸载JobDetail 的时候调用 public void jobUnscheduled(TriggerKey triggerKey) { System.out.println(triggerKey.getName()); } //当trigger来到再也不会触发的时候调用这个方法 public void triggerFinalized(Trigger trigger) { String name trigger.getKey().getName(); System.out.println(获取触发器名称 name); } //当trigger 被暂停时候调用 public void triggerPaused(TriggerKey triggerKey) { System.out.println(被暂停1); } //当trigger组 被暂停时候调用 public void triggersPaused(String triggerGroup) { System.out.println(被暂停2); } ///当trigger从 被暂停 到恢复 时候 调用 public void triggerResumed(TriggerKey triggerKey) { System.out.println(恢复); } ///当trigger组从 被暂停 到恢复 时候 调用 public void triggersResumed(String triggerGroup) { System.out.println(恢复); } //添加工作任务调用 public void jobAdded(JobDetail jobDetail) { System.out.println(添加工作任务); } //删除工作任务 public void jobDeleted(JobKey jobKey) { System.out.println(删除工作任务); } public void jobPaused(JobKey jobKey) { // TODO Auto-generated method stub } public void jobsPaused(String jobGroup) { // TODO Auto-generated method stub } public void jobResumed(JobKey jobKey) { // TODO Auto-generated method stub } public void jobsResumed(String jobGroup) { // TODO Auto-generated method stub } //scheduler产生Error调用 public void schedulerError(String msg, SchedulerException cause) { // TODO Auto-generated method stub } //scheduler被挂起时候调用 public void schedulerInStandbyMode() { // TODO Auto-generated method stub } //scheduler开启的时候调用 public void schedulerStarted() { System.out.println(scheduler 开启 的时候调用); } //scheduler 正在开启的时候调用 ing..... public void schedulerStarting() { System.out.println(scheduler 正在开启的时候调用 ing.....); } // scheduler关闭 的时候调用 public void schedulerShutdown() { System.out.println(scheduler关闭 的时候调用); } //scheduler 正在关闭的时候调用 ing..... public void schedulerShuttingdown() { System.out.println(//scheduler 正在关闭的时候调用 ing.....); } //scheduler 数据被清除了的时候调用 public void schedulingDataCleared() { System.out.println(//scheduler 数据被清除了的时候调用); } } 将下述蓝色代码放于上述【Quartz的简单使用】对应位置 // 3、创建调度器Scheduler并执行 Scheduler scheduler new StdSchedulerFactory().getScheduler(); scheduler.getListenerManager().addSchedulerListener(new MySchedulerListener()); scheduler.scheduleJob(jobDetail, trigger); 运行结果注意看时间 添加工作任务 获取触发器名称trigger1 --------scheduler start ! ------------ at:23-08-22 00-37-43:391, prints: Hello scheduler scheduler 正在开启的时候调用 ing..... scheduler 开启 的时候调用 PrintWordsJob start at:23-08-22 00-37-43:395, prints: Hello Job-74 PrintWordsJob start at:23-08-22 00-37-44:294, prints: Hello Job-62 PrintWordsJob start at:23-08-22 00-37-45:301, prints: Hello Job-84 PrintWordsJob start at:23-08-22 00-37-46:292, prints: Hello Job-19 PrintWordsJob start at:23-08-22 00-37-47:301, prints: Hello Job-82 PrintWordsJob start at:23-08-22 00-37-48:288, prints: Hello Job-42 PrintWordsJob start at:23-08-22 00-37-49:296, prints: Hello Job-19 PrintWordsJob start at:23-08-22 00-37-50:298, prints: Hello Job-4 PrintWordsJob start at:23-08-22 00-37-51:290, prints: Hello Job-10 PrintWordsJob start at:23-08-22 00-37-52:294, prints: Hello Job-78 PrintWordsJob start at:23-08-22 00-37-53:292, prints: Hello Job-42 PrintWordsJob start at:23-08-22 00-37-54:298, prints: Hello Job-49 PrintWordsJob start at:23-08-22 00-37-55:291, prints: Hello Job-13 //scheduler 正在关闭的时候调用 ing..... scheduler关闭 的时候调用 at:23-08-22 00-37-55:397, prints: Hello scheduler --------scheduler shutdown ! ------------ 九、定时任务参数传递问题 将下述蓝色代码放于上述【Quartz的简单使用】1和2之间的位置 // 1、创建JobDetail实例并与PrintWordsJob类绑定(Job执行内容) JobDetail jobDetail JobBuilder.newJob(PrintWordsJob.class) .withIdentity(job1, group1).build(); // 传参 JobDataMap jobDataMapjobDetail.getJobDataMap(); jobDataMap.put(name,传参test); jobDataMap.put(age,11); jobDataMap.put(sex,男); // 2、构建Trigger实例,每隔1s执行一次 Trigger trigger TriggerBuilder.newTrigger().withIdentity(trigger1, triggerGroup1) .startNow()// 立即生效 .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(1)// 每隔1s执行一次 .repeatForever()).build();// 一直执行 同时更新PrintWordsJob.java文件中的代码为以下内容 import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; public class PrintWordsJob implements Job { Override public void execute(JobExecutionContext jobExecutionContext) { String printTime new SimpleDateFormat(yy-MM-dd HH-mm-ss:SSS).format(new Date()); System.out.println(PrintWordsJob start at: printTime , prints: Hello Job- new Random().nextInt(100)); JobDataMap jobDataMap jobExecutionContext.getJobDetail().getJobDataMap(); System.out.println(jobDataMap.get(name).toString() : jobDataMap.get(age).toString() : jobDataMap.get(sex).toString()); } } 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-22 01-00-24:165, prints: Hello scheduler PrintWordsJob start at:23-08-22 01-00-24:176, prints: Hello Job-6 传参test:11:男 PrintWordsJob start at:23-08-22 01-00-25:114, prints: Hello Job-70 传参test:11:男 PrintWordsJob start at:23-08-22 01-00-26:106, prints: Hello Job-54 传参test:11:男 … … … PrintWordsJob start at:23-08-22 01-00-36:104, prints: Hello Job-73 传参test:11:男 at:23-08-22 01-00-36:181, prints: Hello scheduler --------scheduler shutdown ! ------------ 十、任务操作 删除 将下述蓝色代码取代上述【Quartz的简单使用】TimeUnit.MILLISECONDS.sleep(12000); 这里休眠6秒后再执行删除job运行当前删除方法可以看到6秒后直接job方法不再执行 // 睡眠6秒 TimeUnit.MILLISECONDS.sleep(6000); // 删除 scheduler.deleteJob(JobKey.jobKey(job1,group1)); // 睡眠6秒 TimeUnit.MILLISECONDS.sleep(6000); 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-23 00-23-17:971, prints: Hello scheduler PrintWordsJob start at:23-08-23 00-23-17:976, prints: Hello Job-13 PrintWordsJob start at:23-08-23 00-23-18:898, prints: Hello Job-1 PrintWordsJob start at:23-08-23 00-23-19:907, prints: Hello Job-89 PrintWordsJob start at:23-08-23 00-23-20:901, prints: Hello Job-17 PrintWordsJob start at:23-08-23 00-23-21:904, prints: Hello Job-74 PrintWordsJob start at:23-08-23 00-23-22:909, prints: Hello Job-70 PrintWordsJob start at:23-08-23 00-23-23:899, prints: Hello Job-42 at:23-08-23 00-23-29:990, prints: Hello scheduler --------scheduler shutdown ! ------------ 暂停、恢复 将下述蓝色代码取代上述【Quartz的简单使用】TimeUnit.MILLISECONDS.sleep(12000); 这里先暂停job休眠6秒后再恢复job运行程序可以看到6秒后先执行job方法6次后正常时间间隔执行。 // 暂停 scheduler.pauseJob(JobKey.jobKey(job1,group1)); // 睡眠6秒 TimeUnit.MILLISECONDS.sleep(6000); // 恢复 scheduler.resumeJob(JobKey.jobKey(job1,group1)); // 睡眠6秒 TimeUnit.MILLISECONDS.sleep(6000); 运行结果注意看时间 --------scheduler start ! ------------ at:23-08-23 00-26-55:737, prints: Hello scheduler PrintWordsJob start at:23-08-23 00-27-01:747, prints: Hello Job-82 PrintWordsJob start at:23-08-23 00-27-01:747, prints: Hello Job-97 PrintWordsJob start at:23-08-23 00-27-01:747, prints: Hello Job-27 PrintWordsJob start at:23-08-23 00-27-01:747, prints: Hello Job-39 PrintWordsJob start at:23-08-23 00-27-01:747, prints: Hello Job-88 PrintWordsJob start at:23-08-23 00-27-01:747, prints: Hello Job-87 PrintWordsJob start at:23-08-23 00-27-01:747, prints: Hello Job-58 PrintWordsJob start at:23-08-23 00-27-02:666, prints: Hello Job-76 PrintWordsJob start at:23-08-23 00-27-03:670, prints: Hello Job-78 PrintWordsJob start at:23-08-23 00-27-04:678, prints: Hello Job-79 PrintWordsJob start at:23-08-23 00-27-05:667, prints: Hello Job-63 PrintWordsJob start at:23-08-23 00-27-06:676, prints: Hello Job-93 PrintWordsJob start at:23-08-23 00-27-07:667, prints: Hello Job-90 at:23-08-23 00-27-07:745, prints: Hello scheduler --------scheduler shutdown ! ------------ 参考资料 1. https://blog.csdn.net/faramita_of_mine/article/details/123142384?ops_request_miscrequest_idbiz_id102utm_termquartzutm_mediumdistribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-6-123142384.142^v93^chatgptT3_2spm1018.2226.3001.4187 2. https://blog.csdn.net/yoonbongchi/article/details/110579024?ops_request_miscrequest_idbiz_id102utm_termquartzutm_mediumdistribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-110579024.142^v93^chatgptT3_2spm1018.2226.3001.4187 3. https://blog.csdn.net/m0_47010003/article/details/124709983?ops_request_misc%257B%2522request%255Fid%2522%253A%2522169244769016800227480253%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257Drequest_id169244769016800227480253biz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2~all~top_click~default-2-124709983-null-null.142^v93^chatgptT3_2utm_termquartzspm1018.2226.3001.4187