如何中斷正在運行的quartz作業

如何中斷正在運行的quartz作業

讓被鎖死的Thread能被強制中斷,可採用template method 設計模式
建立一個抽象類別InterruptableBaseJob並實作InterruptableJob。

InterruptableBaseJob Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public abstract class InterruptableBaseJob implements InterruptableJob {

protected AtomicReference<Thread> reference = new AtomicReference<>();
protected long executedTime = System.currentTimeMillis();

public abstract void run(JobExecutionContext arg) throws JobExecutionException;

public void execute(JobExecutionContext arg) throws JobExecutionException {
try {
reference.set(Thread.currentThread());
executedTime = System.currentTimeMillis();
run(arg);
} finally {
reference.set(null);
}
}

public void interrupt() {
// 避免誤觸,讓超過20秒的才能被中斷
if (System.currentTimeMillis() - executedTime < 20 * 1000) {
return;
}

Thread thread = reference.getAndSet(null);
if (thread != null) {
thread.interrupt();
LogUtils.system.info("interrupt " + getClass().getName());
}
}
}

create Job have to extends InterruptableBaseJob Example

1
2
3
4
5
6
7
8
@DisallowConcurrentExecution
public class XXXJob extends InterruptableBaseJob {

@Override
public void run(final JobExecutionContext ctx) throws JobExecutionException {
XXXCache.getInstance().update();
}
}

CronScheduler Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class CronScheduler {

private static final CronScheduler instance = new CronScheduler();
private Scheduler scheduler;

private CronScheduler() {
try {
this.scheduler = StdSchedulerFactory.getDefaultScheduler();

this.scheduler.start();

} catch (SchedulerException e) {
LogUtils.err.error("CronScheduler Error.", e);
}
}

public final static CronScheduler getInstance() {
return instance;
}

/**
* 強制中斷任務
* 因為刪除定時任務時,quartz還是會等之前的job完成,才會做移除跟新增job的動作,所以job被鎖死時,可考慮強制中斷
* 能被強制中斷的job必須實作InterruptableJob
* @param scheduleType
* @throws SchedulerException
*/
// 中斷定時任務
public void interruptScheduleJob(ScheduleType scheduleType) throws SchedulerException {
scheduler.interrupt(getJobKey(scheduleType));
}
}

use CronScheduler interruptScheduleJob method Example

1
CronScheduler.getInstance().interruptScheduleJob(ScheduleType.XXXJob);