quartz使用问题

文章目录
  1. 1. 目前解决方案:

接手公司的代码在使用 quartz 中使用了,最近在开发新功能,突然任务都阻塞的,后面发现是是因为改动了一部分代码导致执行了这部分代码

1
2
trigger = TriggerBuilder.newTrigger().withIdentity(jobName, TRIGGER_GROUP_NAME).startAt(startTime).endAt(endTime).build(); 

远程访问线程后显示我没有设置withSchedule 导致一直访问

SELECT * FROM T_QRTZ_LOCKS WHERE SCHED_NAME = ‘quartzScheduler_dq’ AND LOCK_NAME = ‘TRIGGER_ACCESS’ FOR UPDATE

研究了一下在 Quartz 调度框架中,触发器(Trigger)是用于定义任务的启动、结束时间、重复执行间隔等细节的。当没有设置 withSchedule 时,Quartz 默认的行为是认为这个触发器是一个“一次性”触发器,即在 startAt 指定的时间启动,并且不会重复执行。

然而,T_QRTZ_LOCKS 表格是 Quartz 用来管理锁和调度状态的数据库表,LOCK_NAME = 'TRIGGER_ACCESS' 说明当前 Quartz 调度器正在尝试获取对某个资源的锁,可能是在创建或执行触发器时遇到了并发问题。具体来说,这种情况可能是由于以下原因导致的:

  1. 锁的竞争:创建的触发器没有明确的调度计划(例如,没有设置 withSchedule),可能导致 Quartz 试图获取资源的锁,而该锁在其他地方已经被占用。Quartz 会用数据库表 T_QRTZ_LOCKS 来保证分布式环境中不同调度器的协调,防止重复执行。正在尝试访问的锁是 TRIGGER_ACCESS,Quartz 在执行时检查并锁定资源,以防止多个实例同时执行同一个任务。
  2. 没有指定调度计划(Schedule):如果没有设置 withSchedule,Quartz 会认为这个任务没有重复执行的计划,这意味着每次启动时,Quartz 可能会频繁地访问锁,造成资源竞争。

目前解决方案:

  • 设置触发器的调度计划:可以使用 withSchedule 来设置触发器的调度计划

    1
    trigger = TriggerBuilder.newTrigger().withIdentity(jobName, TRIGGER_GROUP_NAME).startAt(startTime).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60)  // 每60秒执行一次.repeatForever())  // 重复执行.build();`
  • 检查并发执行:如果系统是分布式的,确保 Quartz 实例之间的锁定机制正常工作。Quartz 通过数据库锁来防止多个调度器同时处理同一个任务,确保任务的唯一执行。