Java Spring @Scheduled 任务执行两次

springJava

1个回答

写回答

淑气晴光

2025-07-02 09:35

+ 关注

Java
Java

使用Java Spring框架的@Scheduled注解可以实现定时任务的执行。该注解可以标注在方法上,使得这个方法能够按照指定的时间间隔执行。然而,有时候我们发现@Scheduled任务会执行两次,这可能会导致一些意外的结果。在本文中,我们将详细介绍为什么@Scheduled任务会执行两次,并提供解决这个问题的案例代码。

首先,让我们来看一下为什么@Scheduled任务会执行两次。这个问题通常出现在运行多个实例的分布式环境中。当有多个实例同时运行时,每个实例都会尝试执行定时任务。由于每个实例都有自己的调度器,它们会独立地触发任务的执行。这就导致了任务被执行了多次的情况。

为了解决这个问题,我们可以使用分布式锁。分布式锁可以确保在任意时刻只有一个实例能够获得锁,并执行定时任务。当其他实例尝试获取锁时,它们将会被阻塞,直到锁被释放。这样就可以避免任务被重复执行的问题。

下面是一个使用分布式锁解决@Scheduled任务执行两次的案例代码:

Java

import org.Springframework.beans.factory.annotation.Autowired;

import org.Springframework.data.redis.core.RedisTemplate;

import org.Springframework.data.redis.core.script.DefaultRedisScript;

import org.Springframework.scheduling.annotation.Scheduled;

import org.Springframework.stereotype.Component;

@Component

public class ScheduledTask {

@Autowired

private RedisTemplate<String, String> redisTemplate;

@Scheduled(fixedDelay = 1000)

public void scheduledMethod() {

// 生成唯一的任务标识

String taskId = generateTaskId();

// 尝试获取分布式锁

boolean lockAcquired = acquireLock(taskId);

if (lockAcquired) {

try {

// 执行定时任务的逻辑

// ...

} finally {

// 释放分布式锁

releaseLock(taskId);

}

} else {

// 任务已经被其他实例执行

// 可以选择跳过此次执行或者记录日志

// ...

}

}

private String generateTaskId() {

// 根据实际需求生成唯一的任务标识

// ...

}

private boolean acquireLock(String taskId) {

DefaultRedisScript<Boolean> script = new DefaultRedisScript<>();

script.setScriptText("return redis.call('setnx', KEYS[1], ARGV[1]) == 1");

script.setResultType(Boolean.class);

return redisTemplate.execute(script, Collections.singletonList(taskId), "lock");

}

private void releaseLock(String taskId) {

redisTemplate.delete(taskId);

}

}

在上面的例子中,我们使用了Redis作为分布式锁的存储介质。首先,我们生成一个唯一的任务标识,然后尝试获取分布式锁。如果成功获取到锁,就执行定时任务的逻辑,并在最后释放锁。如果获取锁失败,说明任务已经被其他实例执行,我们可以选择跳过此次执行或者记录日志。

通过使用分布式锁,我们可以保证@Scheduled任务在分布式环境中只执行一次,避免了重复执行的问题。这对于一些需要保证幂等性或者避免资源冲突的任务非常有用。

在本文中,我们学习了为什么@Scheduled任务会执行两次,并提供了一个使用分布式锁解决这个问题的案例代码。通过使用分布式锁,我们可以确保在分布式环境中只有一个实例执行定时任务,避免了重复执行的问题。希望本文对你理解和解决@Scheduled任务执行两次问题有所帮助。

举报有用(4)分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号