quartz在job间隔期间内,保证上一个任务执行完后,再去调度下一个任务(转),在多线程情况下的问题

时间:2023-01-05 16:56:13

Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行,这样往往会导致我们执行的数据不正确。如果定时任执行太长,会长时间占用资源,导致其它任务堵塞。

解决办法:

1.在Spring中这时需要设置concurrent的值为false, 禁止并发执行。

 <property name="concurrent" value="true" />

2.当不使用spring的时候就需要在Job的实现类上加@DisallowConcurrentExecution的注释

        @DisallowConcurrentExecution 禁止并发执行多个相同定义的JobDetail, 这个注解是加在Job类上的, 但意思并不是不能同时执行多个Job, 而是不能并发执行同一个Job Definition(由JobDetail定义), 但是可以同时执行多个不同的JobDetail, 举例说明,我们有一个Job类,叫做SayHelloJob, 并在这个Job上加了这个注解, 然后在这个Job上定义了很多个JobDetail, 如sayHelloToJoeJobDetail, sayHelloToMikeJobDetail, 那么当scheduler启动时, 不会并发执行多个sayHelloToJoeJobDetail或者sayHelloToMikeJobDetail, 但可以同时执行sayHelloToJoeJobDetail跟sayHelloToMikeJobDetail

       @PersistJobDataAfterExecution 同样, 也是加在Job上,表示当正常执行完Job后, JobDataMap中的数据应该被改动, 以被下一次调用时用。当使用@PersistJobDataAfterExecution 注解时, 为了避免并发时, 存储数据造成混乱, 强烈建议把@DisallowConcurrentExecution注解也加上。


(但是这样会导致任务的执行不是按照我们预先定义的时间间隔执行)

----------华丽的分割线,以上是转发别人的内容---------------------

我亲自试了加上了@DisallowConcurrentExecution 这个注解,结果发现完全没有任何效果,为什么呢,于是怀着疑问我又写了一个简单的job调度,结果我测试的结果大大的出乎我的意料,测试的过程这里就不描述了,这里告诉大家我的结果,不信的同学可以去试试。

结果:如果job里面用多线程操作的,那么会让这个注释失效,因为这个注释是改变状态,而多线程会使状态无效,如果你想要调度任务,又想使用多线程(即同一个调度(触发器)调用多个job),建议和我一样把多线程的部分提到前面启动哪一个部分。这样就可以具备多线程又可以使得注释有效。