You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在两个Spring定时批处理任务间设置执行延迟?

实现两个定时任务的互斥执行

要让两个定时任务互相等待,确保同一时间只有一个任务在执行,核心是引入共享互斥锁,让两个任务竞争同一把锁,锁被占用时则阻塞等待,直到持有锁的任务执行完成释放锁。

方案1:使用ReentrantLock实现灵活互斥

首先创建一个共享锁组件:

@Component
public class JobLock {
    // 公平锁模式:按请求顺序分配锁,避免任务饥饿;无需公平性可省略true参数
    public final ReentrantLock lock = new ReentrantLock(true);
}

修改两个定时任务,注入共享锁并在执行逻辑前后加锁/释放锁:

@Component
public class Job1 {

    private final JobLock jobLock;

    public Job1(JobLock jobLock) {
        this.jobLock = jobLock;
    }

    @Scheduled(fixedRate = 20000)
    public void execute() {
        try {
            // 阻塞等待获取锁,直到前一个任务执行完成
            jobLock.lock.lock();
            // --------------------------
            // 这里编写你的业务逻辑
            System.out.println("Job1 开始执行");
            Thread.sleep(5000); // 模拟业务耗时
            System.out.println("Job1 执行完成");
            // --------------------------
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            // 必须在finally中释放锁,防止异常导致锁无法释放
            jobLock.lock.unlock();
        }
    }
}
@Component
public class Job2 {

    private final JobLock jobLock;

    public Job2(JobLock jobLock) {
        this.jobLock = jobLock;
    }

    @Scheduled(fixedRate = 20000)
    public void execute() {
        try {
            jobLock.lock.lock();
            // --------------------------
            // 这里编写你的业务逻辑
            System.out.println("Job2 开始执行");
            Thread.sleep(3000); // 模拟业务耗时
            System.out.println("Job2 执行完成");
            // --------------------------
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            jobLock.lock.unlock();
        }
    }
}

方案2:使用synchronized同步块(简单场景)

如果不需要ReentrantLock的高级特性,也可以用共享对象作为锁,通过synchronized实现互斥:

创建共享锁对象:

@Component
public class SharedLock {
    public final Object lock = new Object();
}

修改任务代码:

@Component
public class Job1 {

    private final SharedLock sharedLock;

    public Job1(SharedLock sharedLock) {
        this.sharedLock = sharedLock;
    }

    @Scheduled(fixedRate = 20000)
    public void execute() {
        synchronized (sharedLock.lock) {
            // 业务逻辑
            System.out.println("Job1 执行中");
            Thread.sleep(5000);
        }
    }
}

Job2的修改方式和Job1完全一致,只需注入同一个SharedLock对象即可。

注意事项

  • fixedRate是以上次任务开始时间为基准计算下一次执行时间,如果任务耗时超过20秒,下一次触发会立即等待锁释放;若希望以上次任务结束时间为基准,改用fixedDelay = 20000,即任务完成后再过20秒才触发下一次。
  • 若不想无限等待锁,可以使用ReentrantLock的tryLock(long timeout, TimeUnit unit)方法设置等待超时,超时后可选择跳过本次执行。

内容的提问来源于stack exchange,提问作者Prakash kumar mallick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 04:25:13