当前位置: 首页 > news >正文

云空间可以做网站wordpress导航菜单位置

云空间可以做网站,wordpress导航菜单位置,嘉兴南湖区建设局网站,昆明 网站建设文章目录 【README】【1】Quartz任务调度框架【1.1】Job调度任务【1.2】任务调度触发器Trigger【1.3】\*Quartz框架执行调度任务代码实践【1.3.1】硬编码执行Quartz调度任务【1.3.2】基于生产者模式执行quartz调度任务#xff08;推荐#xff09; 【2】spring集成Quartz【2.1… 文章目录 【README】【1】Quartz任务调度框架【1.1】Job调度任务【1.2】任务调度触发器Trigger【1.3】\*Quartz框架执行调度任务代码实践【1.3.1】硬编码执行Quartz调度任务【1.3.2】基于生产者模式执行quartz调度任务推荐 【2】spring集成Quartz【2.1】spring管理quartz组件对象【2.1.1】spring管理quartz的Job【2.1.2】spring管理quartz的JobDetail【2.1.3】spring管理quartz的Trigger【2.1.4】spirng管理quartz的Scheduler 【2.2】spring启动quartz调度器执行调度任务 【3】JDK Timer定时器【3.1】JDK Timer基础知识回顾【3.2】定时器任务单次执行【3.2.1】给定延迟时间之后执行单次任务【3.2.2】在给定时间点执行单次任务 【3.3】 定时器任务重复执行【3.3.1】在给定延迟时间后重复执行【3.2.2】在给定时间点重复执行【3.3.3】定时器任务重复执行注意点 【3.4】取消调度器与调度任务【3.4.1】 在run方法里取消调度任务 【3.5】定时器Timer与调度线程池对比【3.5.1】调度线程池执行调度任务回顾【3.5.2】定时器与调度线程池ScheduledExecutorService对比 【README】 本文部分内容总结自《spring揭秘》作者王福强非常棒的一本书墙裂推荐 本文部分内容总结自 https://juejin.cn/post/7158071449314394119 本文代码参见 github-springDiscover-chapter31 【1】Quartz任务调度框架 1Quartz是一款开源的任务调度框架 官网介绍参见 quartz-scheduler 官网介绍总结翻译 quartz是一款功能丰富的开源作业调度库可以集成几乎任何java应用从最小的单体应用到最大的电子商务系统。 quartz能够用于创建简单或复杂的调度以执行数十数百数万个作业这些作业的任务可以被定义为标准的java组件可以执行你编程让它们做的任何操作。quartz调度器包含许多企业级功能如支持JTA事务与集群。应用场景 定时执行业务逻辑如数据同步发送短信每隔一段时间执行业务逻辑如每隔5秒发送1次心跳 2相对于JDK的Timer之类的简单任务调度程序来说Quartz拥有丰富的功能如下 允许批处理任务状态的持久化批处理任务的远程调度基于web的监控接口集群支持 同一时刻只有一个任务执行当一个任务宕机之后其它服务会接管这个任务插件式的可扩展性 3Quartz组件清单 Job 抽象调度任务作业JobDetail封装job的详细信息如job名称组名称job的classJobDataMap等Trigger触发器抽象job触发规则如执行开始时间结束时间执行频率Scheduler调度器 使用Trigger定义的规则执行jobJobBuilderJob生成器用于创建Job实例TriggerBuilderTrigger生成器用于创建Trigger实例JobExecutionContextJob运行时上下文JobDataMap 封装参数键值对用于Job与JobDetail的数据交互 4Quartz基本组件关系如下 5使用 quartz任务调度框架需要引入对应maven依赖如下 dependencygroupIdorg.quartz-scheduler/groupIdartifactIdquartz/artifactIdversion2.3.2/version /dependency【1.1】Job调度任务 1quartz中调度任务job定义 public interface Job {void execute(JobExecutionContext var1) throws JobExecutionException; }2调度任务实现job接口 public class TomScheduleJob implements Job {Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// do sth.System.out.println(MyScheduleJob#当前时间 BusiDatetimeUtils.getNowText());} }【1.2】任务调度触发器Trigger 1触发器定义job触发规则如每隔10分钟执行1次每天早上7点9点准时执行1次 2触发器Trigger定义如下 public interface Trigger extends Serializable, Cloneable, ComparableTrigger {long serialVersionUID -3904243490805975570L;int MISFIRE_INSTRUCTION_SMART_POLICY 0;int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY -1;int DEFAULT_PRIORITY 5;TriggerKey getKey();JobKey getJobKey();String getDescription();String getCalendarName();JobDataMap getJobDataMap();int getPriority();boolean mayFireAgain();Date getStartTime();Date getEndTime();Date getNextFireTime();Date getPreviousFireTime();Date getFireTimeAfter(Date var1);Date getFinalFireTime();int getMisfireInstruction();TriggerBuilder? extends Trigger getTriggerBuilder();ScheduleBuilder? extends Trigger getScheduleBuilder();boolean equals(Object var1);int compareTo(Trigger var1); // ... }2触发器的两种主要实现 SimpleTrigger指定基于时间间隔的调度规则触发规则CronTrigger指定基于cron表达式的调度规则包括但不限于时间间隔还可以指定具体时间执行触发规则更加灵活 【1.3】*Quartz框架执行调度任务代码实践 【1.3.1】硬编码执行Quartz调度任务 【TomQuartzJob】 public class TomQuartzJob implements Job {Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// do sth.System.out.println(TomQuartzJob#当前时间 BusiDatetimeUtils.getNowText());} }【TomQuartzJobMain】 public class TomQuartzJobMain {public static void main(String[] args) throws Exception {executeScheduleJob();}private static void executeScheduleJob() throws ParseException, SchedulerException {// 新建触发器SimpleTriggerImpl simpleTrigger new SimpleTriggerImpl(tomSimpleTrigger, tomSimpleTriggerGroup, new Date(), null, SimpleTriggerImpl.REPEAT_INDEFINITELY, 5000); // 每隔5秒执行1次CronTriggerImpl cronTrigger new CronTriggerImpl(tomSimpleTrigger, tomSimpleTriggerGroup, */5 * * * * ?);// 新建调度器Scheduler scheduler new StdSchedulerFactory().getScheduler();scheduler.start();// 新建调度任务详情JobDetailImpl tomJobDetail new JobDetailImpl(tomJobDetail, TomQuartzJob.class);// 新增调度任务这里是新增并没有执行执行由触发器来负责 // scheduler.scheduleJob(tomJobDetail, simpleTrigger);scheduler.scheduleJob(tomJobDetail, cronTrigger);} }【1.3.2】基于生产者模式执行quartz调度任务推荐 1基于生成器模式执行调度任务 参考 quick-start 【TomTimeRemindJob】 public class TomTimeRemindJob implements Job {Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println();context.getMergedJobDataMap().forEach((k,v)- System.out.println(k v));context.getJobDetail().getJobDataMap().forEach((k,v)- System.out.println(k v));System.out.println(TomTimeRemindJob now BusiDatetimeUtils.getNowText());} }【TomTimeRemindJobMain】 public class TomTimeRemindJobMain {public static void main(String[] args) throws SchedulerException {// 创建调度器实例Scheduler scheduler StdSchedulerFactory.getDefaultScheduler();// 开启调度器scheduler.start();// 执行调度作业executeScheduleJob(scheduler);// 关闭调度器 // scheduler.shutdown();}private static void executeScheduleJob(Scheduler scheduler) throws SchedulerException {// 创建JobDetail并与TomTimeRemindJob 绑定JobDetail jobDetail JobBuilder.newJob(TomTimeRemindJob.class).withIdentity(tomJob01, tomJob01Group).build();// 立即触发作业执行每5秒重复一次Trigger simpleTrigger TriggerBuilder.newTrigger().withIdentity(tomTrigger01, tomTrigger01Group).startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();// 告诉quartz使用我们的触发器调度作业scheduler.scheduleJob(jobDetail, simpleTrigger);} }【2】spring集成Quartz 1通过上述代码【TomTimeRemindJobMain】 本文发现使用Quartz框架执行调度任务需要依赖以下4个组件Job JobDetail Trigger Scheduler Job调度任务 JobDetail 用于封装job详细信息 Trigger触发器定义触发规则 Scheduler调度器根据触发器的规则执行调度任务作业 2可以想到spring集成Quartz的底层原理 把JobJobDetail SimpleTrigger Scheduler对象创建与依赖关系装配由spring来完成无需客户端实现 spring采用工厂方法FactoryBean来管理quartz调度任务所需组件 3spring集成Quartz需要新增maven依赖如下 dependencygroupIdorg.springframework/groupIdartifactIdspring-context-support/artifactIdversion6.1.10/version/dependency【2.1】spring管理quartz组件对象 1本章节部分内容总结自 spring-quartz-schedule 【2.1.1】spring管理quartz的Job 1spring提供了QuartzJobBean用于抽象调度任务自定义调度任务需要继承QuartzJobBean并重写executeInternal()方法 2QuartzJobBean定义注意quartz的JobDetail封装了Job的class对象由JobDetail实例化job所以spring无需注册job public abstract class QuartzJobBean implements Job {public QuartzJobBean() {}public final void execute(JobExecutionContext context) throws JobExecutionException {try {BeanWrapper bw PropertyAccessorFactory.forBeanPropertyAccess(this);MutablePropertyValues pvs new MutablePropertyValues();pvs.addPropertyValues(context.getScheduler().getContext());pvs.addPropertyValues(context.getMergedJobDataMap());bw.setPropertyValues(pvs, true);} catch (SchedulerException var4) {throw new JobExecutionException(var4);}this.executeInternal(context);}protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException; }【自定义job继承QuartzJobBean】TomSpringQuartzJobBean public class TomSpringQuartzJobBean extends QuartzJobBean {Overrideprotected void executeInternal(JobExecutionContext context) throws JobExecutionException {System.out.println(TomSpringQuartzJobBean #当前时间 BusiDatetimeUtils.getNowText());} }【2.1.2】spring管理quartz的JobDetail 1在quartz中 job抽象了调度任务而job的上下文信息由JobDetail封装Job与JobDetail的数据交互通过JobDataMap实现 2spring注册JobDetail有两种方式 方式1 JobDetailFactoryBean 注册JobDetail 推荐 方式2 通过 MethodInvokingJobDetailFactoryBean 注册JobDetail 本文不介绍 【springquartz.xml】 JobDetailFactoryBean 注册JobDetail ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!-- 通过 JobDetailFactoryBean 注册JobDetail --bean classorg.springframework.scheduling.quartz.JobDetailFactoryBeanproperty namename valuetomJob /property namegroup valuetomJobGroup /property namejobClass valuecom.tom.springnote.chapter31schedule.springquartz.SpringScheduleJob /property namedurability valuetrue /property namedescription valuetomJobDetail /property namejobDataMapmapentry keymessage valuehello world /entry keycity valuechengdu //map/property/bean /beans【2.1.3】spring管理quartz的Trigger 1trigger触发器定义了执行调度任务的规则 如每5秒执行1次 2spring也是通过FactoryBean注册Trigger SimpleTriggerFactoryBean 简单触发器CronTriggerFactoryBean 带有cron表达式的触发器 【springquartz.xml】 SimpleTriggerFactoryBean 注册Trigger ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!-- 通过 JobDetailFactoryBean 注册JobDetail --bean idtomJobDetail classorg.springframework.scheduling.quartz.JobDetailFactoryBeanproperty namename valuetomJob /property namegroup valuetomJobGroup /property namejobClass valuecom.tom.springnote.chapter31schedule.springquartz.SpringScheduleJob /property namedurability valuetrue /property namedescription valuetomJobDetail /property namejobDataMapmapentry keymessage valuehello world /entry keycity valuechengdu //map/property/bean!-- 通过 SimpleTriggerFactoryBean 注册触发器 --bean classorg.springframework.scheduling.quartz.SimpleTriggerFactoryBeanproperty namename valuetomTrigger /property namegroup valuetomTriggerGroup /property namejobDetail reftomJobDetail /property namerepeatInterval value5000 / !-- 单位毫秒每5秒执行1次--property namerepeatCount value-1 / !-- -1表示永远重复 --/bean!-- 通过 CronTriggerFactoryBean 注册触发器 --bean classorg.springframework.scheduling.quartz.CronTriggerFactoryBeanproperty namename valuetomCronTrigger /property namegroup valuetomCronTriggerGroup /property namejobDetail reftomJobDetail /property namecronExpression ref*/3 * * * * ? / !-- 每3秒执行1次--/bean/beans3补充 多个trigger定义的规则可以同时作用于同一个JobDetail 或Job 本文认为多个Trigger规则的组合太过复杂1个trigger对应1个Job足够满足日常业务需求本文不再深入研究多个trigger组合的情况有兴趣的同学自行研究 【2.1.4】spirng管理quartz的Scheduler 1scheduler调度器使用触发器Trigger定义的规则执行调度任务job 2spring通过SchedulerFactoryBean注册scheduler 【springquartz.xml】 SchedulerFactoryBean注册scheduler ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!-- 通过 JobDetailFactoryBean 注册JobDetail --bean idtomJobDetail classorg.springframework.scheduling.quartz.JobDetailFactoryBeanproperty namename valuetomJob /property namegroup valuetomJobGroup /property namejobClass valuecom.tom.springnote.chapter31schedule.springquartz.TomSpringQuartzJobBean /property namedurability valuetrue /property namedescription valuetomJobDetail /property namejobDataMapmapentry keymessage valuehello world /entry keycity valuechengdu //map/property/bean!-- 通过 SimpleTriggerFactoryBean 注册触发器 --bean idtomSimpleTrigger classorg.springframework.scheduling.quartz.SimpleTriggerFactoryBeanproperty namename valuetomTrigger /property namegroup valuetomTriggerGroup /property namejobDetail reftomJobDetail /property namerepeatInterval value5000 / !-- 单位毫秒每5秒执行1次--property namerepeatCount value-1 / !-- -1表示永远重复 --/bean!-- 通过 CronTriggerFactoryBean 注册触发器 --bean idtomCronTrigger classorg.springframework.scheduling.quartz.CronTriggerFactoryBeanproperty namename valuetomCronTrigger /property namegroup valuetomCronTriggerGroup /property namejobDetail reftomJobDetail /property namecronExpression ref*/3 * * * * ? / !-- 每3秒执行1次--/bean!-- 通过SchedulerFactoryBean注册scheduler --bean classorg.springframework.scheduling.quartz.SchedulerFactoryBeanproperty nametriggers !-- 可以装配多个触发器当然日常开发1个足够 --listref beantomSimpleTrigger /ref beantomCronTrigger //list/property/bean /beans【2.2】spring启动quartz调度器执行调度任务 1spring容器ApplicationContext启动时SchedulerFactoryBean所管理的调度器Scheduler跟着自动启动且Scheduler随着ApplicationContext的关闭而自动关闭 当调度任务的所有对象实例注册到ioc容器后ApplicationContext启动时Scheduler也启动Scheduler立即开始执行调度任务 【TomSpringQuartzJobBeanMain】 public class TomSpringQuartzJobBeanMain {public static void main(String[] args) {ClassPathXmlApplicationContext springContext new ClassPathXmlApplicationContext(chapter31schedule/springquartz.xml);((AbstractApplicationContext) springContext).registerShutdownHook();} }【执行效果】 2个调度任务在执行因为有2个触发器tomSimpleTrigger-每5秒执行1次tomCronTrigger-每3秒执行1次 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:23.623 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:24.002 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:27.000 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:28.505 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:30.000 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:33.010 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:33.501 TomSpringQuartzJobBean #当前时间2024-10-13 21:42:36.003【3】JDK Timer定时器 【3.1】JDK Timer基础知识回顾 1Timer定时器组件 TimerTask抽象调度任务Timer抽象调度器用于定义任务触发规则并执行调度任务 类似于肩负了quartz的Scheduler与Trigger职责 只能配置简单规则不能配置cron表达式 2Timer使用TimerTask抽象调度任务自定义调度任务需要继承TimerTask 由代码可知 TimerTask本质上是Runnable即可以提交给线程的任务 public abstract class TimerTask implements Runnable {// ... }3部分代码总结自 java-timer-and-timertask 【3.2】定时器任务单次执行 【3.2.1】给定延迟时间之后执行单次任务 1在当前时间等待给定延迟时间之后执行调度任务 【OnceTimerTaskExecuteAfterDelayMain】给定延迟时间之后仅执行1次调度任务 public class OnceTimerTaskExecuteAfterDelayMain {public static void main(String[] args) {TimerTask timerTask new TimerTask() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());}};// 通过jdk 定时器执行调度任务Timer timer new Timer();System.out.println(当前时间 BusiDatetimeUtils.getNowText());// 在给定延迟时间(5s)之后执行调度任务仅执行1次timer.schedule(timerTask, 5000);System.out.println(after timer.schedule()新增调度任务之后);try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {throw new RuntimeException(e);}// 取消调度器执行(主线程结束)timer.cancel();System.out.println(主线程结束 当前时间 BusiDatetimeUtils.getNowText());} } public void schedule(TimerTask task, long delay) { if (delay 0)throw new IllegalArgumentException(Negative delay.);sched(task, System.currentTimeMillis()delay, 0); // period0 表示当前任务仅执行1次 } private void sched(TimerTask task, long time, long period) { // ... }【解说】period参数表示2个相邻任务执行的时间间隔单位毫秒 若为0表示仅执行1次 若为整数表示时间间隔 【执行效果】 当前时间2024-10-16 20:51:52.281 after timer.schedule()新增调度任务之后 线程id15 当前时间2024-10-16 20:51:57.298 主线程结束 当前时间2024-10-16 20:51:57.298【3.2.2】在给定时间点执行单次任务 1在给定时间点执行调度任务 【OnceTimerTaskExecuteAtGivenTime】 在给定时间点执行调度任务仅执行1次 public class OnceTimerTaskExecuteAtGivenTime {public static void main(String[] args) {TimerTask timerTask new TimerTask() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());}};// 通过jdk 定时器执行调度任务Timer timer new Timer();System.out.println(当前时间 BusiDatetimeUtils.getNowText());// 在给定时间点当前时间加5秒的时间执行调度任务仅执行1次timer.schedule(timerTask, BusiDatetimeUtils.timeAfterSecond(5));System.out.println(after timer.schedule()新增调度任务之后);try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {throw new RuntimeException(e);}// 取消调度器执行(主线程结束)timer.cancel();System.out.println(主线程结束 当前时间 BusiDatetimeUtils.getNowText());} } public void schedule(TimerTask task, Date time) {sched(task, time.getTime(), 0); // period0 表示仅执行1次 }【执行效果】 当前时间2024-10-16 20:55:09.981 after timer.schedule()新增调度任务之后 线程id15 当前时间2024-10-16 20:55:14.984 主线程结束 当前时间2024-10-16 20:55:14.986【3.3】 定时器任务重复执行 【3.3.1】在给定延迟时间后重复执行 1使用Timer定时器在给定延迟时间后重复执行调度任务 【RepeatableTimerTaskExecuteAfterDelayMain】 public class RepeatableTimerTaskExecuteAfterDelayMain {public static void main(String[] args) {TimerTask timerTask new TimerTask() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());}};// 通过jdk 定时器执行调度任务Timer timer new Timer();System.out.println(当前时间 BusiDatetimeUtils.getNowText());// 在给定延迟时间(5s)之后执行调度任务间隔2秒重复执行timer.schedule(timerTask, 5000, 2000);System.out.println(after timer.schedule()新增调度任务之后);try {TimeUnit.SECONDS.sleep(10); // 睡眠10s后关闭定时器以便调度任务可以重复执行} catch (InterruptedException e) {throw new RuntimeException(e);}// 取消调度器执行(主线程结束)timer.cancel();System.out.println(主线程结束 当前时间 BusiDatetimeUtils.getNowText());} }【执行效果】 当前时间2024-10-16 21:01:49.933 after timer.schedule()新增调度任务之后 线程id15 当前时间2024-10-16 21:01:54.950 线程id15 当前时间2024-10-16 21:01:56.951 线程id15 当前时间2024-10-16 21:01:58.957 主线程结束 当前时间2024-10-16 21:01:59.946【3.2.2】在给定时间点重复执行 【RepeatableTimerTaskExecuteAtGivenTime】 public class RepeatableTimerTaskExecuteAtGivenTime {public static void main(String[] args) {TimerTask timerTask new TimerTask() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());}};// 通过jdk 定时器执行调度任务Timer timer new Timer();System.out.println(当前时间 BusiDatetimeUtils.getNowText());// 在给定时间点当前时间加5秒的时间执行调度任务间隔2s重复执行timer.schedule(timerTask, BusiDatetimeUtils.timeAfterSecond(5), 2000);System.out.println(after timer.schedule()新增调度任务之后);try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}// 取消调度器执行(主线程结束)timer.cancel();System.out.println(主线程结束 当前时间 BusiDatetimeUtils.getNowText());} }【执行效果】 当前时间2024-10-16 21:07:12.258 after timer.schedule()新增调度任务之后 线程id15 当前时间2024-10-16 21:07:17.260 线程id15 当前时间2024-10-16 21:07:19.261 线程id15 当前时间2024-10-16 21:07:21.275 主线程结束 当前时间2024-10-16 21:07:22.261【3.3.3】定时器任务重复执行注意点 1 若一个任务执行耗时大于调度间隔或周期period则会延迟整个执行链无论是在延迟时间后还是给定时间点执行 【RepeatableTimerTaskDelayWholeChainAtGivenTime】 public class RepeatableTimerTaskDelayWholeChainAtGivenTime {public static void main(String[] args) {TimerTask timerTask new TimerTask() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());try {TimeUnit.SECONDS.sleep(5); // 模拟单个任务执行耗时5秒} catch (InterruptedException e) {throw new RuntimeException(e);}}};// 通过jdk 定时器执行调度任务Timer timer new Timer();System.out.println(当前时间 BusiDatetimeUtils.getNowText());// 在给定时间点当前时间加5秒的时间执行调度任务间隔2s重复执行timer.schedule(timerTask, BusiDatetimeUtils.timeAfterSecond(1), 2000);System.out.println(after timer.schedule()新增调度任务之后);try {TimeUnit.SECONDS.sleep(30); // 延迟30秒等待执行重复调度任务} catch (InterruptedException e) {throw new RuntimeException(e);}// 取消调度器执行(主线程结束)timer.cancel(); System.out.println(主线程结束 当前时间 BusiDatetimeUtils.getNowText());} }【执行效果】 程序中设置定时器每隔2s执行调度任务而运行效果是每隔5s执行调度任务 原因是任务执行睡眠5s模拟了业务逻辑耗时当上一个任务执行完成后下一个任务才会执行即单个任务执行耗时过长会延迟整体任务调度 当前时间2024-10-16 21:36:40.218 after timer.schedule()新增调度任务之后 线程id15 当前时间2024-10-16 21:36:41.222 线程id15 当前时间2024-10-16 21:36:46.236 线程id15 当前时间2024-10-16 21:36:51.247 线程id15 当前时间2024-10-16 21:36:56.258 线程id15 当前时间2024-10-16 21:37:01.272 线程id15 当前时间2024-10-16 21:37:06.285 主线程结束 当前时间2024-10-16 21:37:10.224【3.4】取消调度器与调度任务 1取消调度器执行的方法 调用 Timer.cancel()方法取消调度器 若调度器有任务运行则不结束 若调度器没有任务运行则可以结束 2取消调度任务的方法 方法1 在TimerTask内部run方法执行cancel()方法取消当前调度任务执行方法2 在TimerTask内部run()方法中强行终止当前线程执行 【3.4.1】 在run方法里取消调度任务 【CancelRepeatableTimerTaskInsideRun】 public class CancelRepeatableTimerTaskInsideRun {public static void main(String[] args) {TimerTask timerTask new TimerTask() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());cancel(); // 取消当前调度任务 本来是重复调度结果仅执行1次}};// 通过jdk 定时器执行调度任务Timer timer new Timer();System.out.println(当前时间 BusiDatetimeUtils.getNowText());// 在给定时间点当前时间加5秒的时间执行调度任务间隔2s重复执行timer.schedule(timerTask, BusiDatetimeUtils.timeAfterSecond(5), 2000);System.out.println(after timer.schedule()新增调度任务之后);try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}// 取消调度器执行(主线程结束)timer.cancel();System.out.println(主线程结束 当前时间 BusiDatetimeUtils.getNowText());} }【执行效果】 当前时间2024-10-16 21:48:59.496 after timer.schedule()新增调度任务之后 线程id15 当前时间2024-10-16 21:49:04.501 主线程结束 当前时间2024-10-16 21:49:09.510【3.5】定时器Timer与调度线程池对比 【3.5.1】调度线程池执行调度任务回顾 【RepeatableTaskExecuteBySchedulerThreadPoolMain】使用调度线程池执行重复任务 public class RepeatableTaskExecuteBySchedulerThreadPoolMain {public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService Executors.newScheduledThreadPool(1); // 不要这样用本文仅演示Runnable task new Runnable() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());}};// 重复任务间隔2s执行1次scheduledExecutorService.scheduleAtFixedRate(task, 0, 2000, TimeUnit.MILLISECONDS);} }【执行效果】 线程id15 当前时间2024-10-16 22:03:46.625 线程id15 当前时间2024-10-16 22:03:48.580 线程id15 当前时间2024-10-16 22:03:50.579 线程id15 当前时间2024-10-16 22:03:52.578【注意】 实际开发过程中不要使用 Executors.newScheduledThreadPool(1) 如下面代码所示该方法初始化的最大线程个数无限大这是有问题的 线程个数无限大会导致cpu时间片被耗尽切换不到或无法及时切换到正常业务逻辑的线程上导致系统假死 public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,new DelayedWorkQueue());}【3.5.2】定时器与调度线程池ScheduledExecutorService对比 1定时器Timer与调度线程池ScheduledExecutorService对比 定时器Timer对系统时钟变化非常敏感而调度线程池不会定时器Timer只有1个执行线程 而调度线程池可以配置多个TimerTask内部run方法执行抛出运行时异常则当前线程被杀死导致后续任务不执行而调度线程池中的线程抛出异常仅运行中的任务被取消但线程还存在即其他任务还是可以被执行 2模拟TimerTask的run方法内部抛出异常 public class RepeatableTimerTaskExecuteThrowException {public static void main(String[] args) {TimerTask timerTask new TimerTask() {Overridepublic void run() {System.out.printf(线程id%s 当前时间%s \n, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());throw new RuntimeException(mock runtime exception);}};// 通过jdk 定时器执行调度任务Timer timer new Timer();System.out.println(当前时间 BusiDatetimeUtils.getNowText());// 在给定时间点当前时间加5秒的时间执行调度任务间隔2s重复执行timer.schedule(timerTask, BusiDatetimeUtils.timeAfterSecond(5), 2000);System.out.println(after timer.schedule()新增调度任务之后);try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}// 取消调度器执行(主线程结束)timer.cancel();System.out.println(主线程结束 当前时间 BusiDatetimeUtils.getNowText());} }【执行效果】 显然若TimerTask内部run方法抛出运行时异常则整个定时器执行完成定时器线程被杀死 当前时间2024-10-16 22:12:37.801 after timer.schedule()新增调度任务之后 线程id15 当前时间2024-10-16 22:12:42.803 Exception in thread Timer-0 java.lang.RuntimeException: mock runtime exceptionat com.tom.springnote.chapter31schedule.origintimer.RepeatableTimerTaskExecuteThrowException$1.run(RepeatableTimerTaskExecuteThrowException.java:22)at java.base/java.util.TimerThread.mainLoop(Timer.java:566)at java.base/java.util.TimerThread.run(Timer.java:516) 主线程结束 当前时间2024-10-16 22:12:47.806 3模拟调度线程池ScheduledExecutorService的run方法内部抛出异常 【RepeatableTaskExecuteBySchedulerThreadPoolThrowExceptionMain】 public class RepeatableTaskExecuteBySchedulerThreadPoolThrowExceptionMain {static class BusiTask implements Runnable {private String flag;public BusiTask(String flag) {this.flag flag;}Overridepublic void run() {System.out.printf(flag%s, 线程id%s 当前时间%s \n, flag, Thread.currentThread().getId(), BusiDatetimeUtils.getNowText());if (Objects.equals(exception, flag)) {throw new RuntimeException(mock runtime exception);}}}public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService Executors.newScheduledThreadPool(2);// 重复任务间隔2s执行1次scheduledExecutorService.scheduleAtFixedRate(new BusiTask(exception), 0, 2000, TimeUnit.MILLISECONDS);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}// 第2次添加任务scheduledExecutorService.scheduleAtFixedRate(new BusiTask(zhangsan), 0, 2000, TimeUnit.MILLISECONDS);} }【执行效果】 显然即便抛出异常 我们还是可以向调度线程池添加调度任务 flagexception, 线程id15 当前时间2024-10-16 22:25:34.802 flagzhangsan, 线程id15 当前时间2024-10-16 22:25:36.750 flagzhangsan, 线程id15 当前时间2024-10-16 22:25:38.756 flagzhangsan, 线程id15 当前时间2024-10-16 22:25:40.764
http://www.hkea.cn/news/14381074/

相关文章:

  • 购买了网站如何使用宝安中心医院
  • 网站建设规划书txt微盘营销策略有哪几种
  • 展展示型网站开发网站建设培训 ppt
  • 成都建站提供商百度搜寻网站缩略图如何添加
  • 东莞seo托管竞价页面网站做优化
  • 建站空间哪个好哪里有门户网站开发
  • 网站服务器错误403北京优化seo排名
  • 铭泰东莞网站建设电子商务网站开发系统平台
  • 华为erp企业管理系统软件网站优化推广哪家好
  • xampp做网站九江市建设规划局网站
  • 怎样创造一个网站wordpress小程序前端
  • 免费申请网站域名软件设计的过程
  • 产品网站建设个旧市建设局网站
  • 深圳市做网站的做系统网站提醒有风险
  • 更改wordpress程序站点网址在线网站开发培训
  • 网站开发模块学些什么html友情链接代码
  • 网站更新和维护怎么做做网站的版式会侵权吗
  • 请人做网站谁来维护鞍山网站建设公司
  • 深圳制作网站主页app软件开发公司排行
  • 网站开发从什么学起wordpress和域名
  • 山东临沂网站推广公司注册地址费用
  • 高仿网站源码asp网站开发的主要困难
  • 做个电商网站温州做微网站设计
  • 科右中旗网站建设做网站横幅的图片多大
  • 中国有名的模版网站常见的网络推广工具
  • 怎么诊断网站邢台物流网站建设
  • 推广网站可以做跳转吗wordpress啥意思
  • 济南高新区建设局网站极简风格wordpress主题
  • 一个网站需要多少容量太原百度关键词优化
  • 清远网站开发注册个网站域名多少钱一年