|
springboot制作,每隔30分钟执行一次任务,本次任务没有执行完,下次任务不允许执行
在 Spring Boot 中,你可以使用 Spring 的 `@Scheduled` 注解来实现定时任务,同时通过控制任务的执行状态来确保本次任务没有执行完时,下次任务不允许执行。以下是具体的实现步骤和示例代码:
### 1. 添加依赖
确保你的 `pom.xml` 文件中包含 Spring Boot 的相关依赖,特别是 `spring-boot-starter` 和 `spring-boot-starter-web`。
```xml:pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
```
### 2. 启用定时任务
在 Spring Boot 主应用类上添加 `@EnableScheduling` 注解来启用定时任务功能。
```java:src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
### 3. 创建定时任务类
创建一个包含定时任务的类,并使用 `@Scheduled` 注解来定义任务的执行时间。同时,使用一个布尔变量来控制任务的执行状态。
```java:src/main/java/com/example/demo/ScheduledTask.java
package com.example.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
private static final Logger logger = LoggerFactory.getLogger(ScheduledTask.class);
private boolean isTaskRunning = false;
@Scheduled(fixedRate = 30 * 60 * 1000) // 每30分钟执行一次
public void performTask() {
if (isTaskRunning) {
logger.info("上一次任务还未执行完,本次任务跳过。");
return;
}
try {
isTaskRunning = true;
logger.info("任务开始执行。");
// 模拟任务执行
Thread.sleep(10000); // 模拟任务执行时间
logger.info("任务执行完成。");
} catch (InterruptedException e) {
logger.error("任务执行被中断: ", e);
} finally {
isTaskRunning = false;
}
}
}
```
### 代码解释
- `@EnableScheduling`:在主应用类上添加该注解,启用 Spring 的定时任务功能。
- `@Scheduled(fixedRate = 30 * 60 * 1000)`:在 `performTask` 方法上添加该注解,指定任务每隔 30 分钟执行一次。
- `isTaskRunning`:一个布尔变量,用于控制任务的执行状态。当任务开始执行时,将其设置为 `true`;任务执行完成后,将其设置为 `false`。
- 在 `performTask` 方法中,首先检查 `isTaskRunning` 的状态。如果为 `true`,表示上一次任务还未执行完,本次任务将跳过。
通过以上步骤,你可以实现一个每隔 30 分钟执行一次的定时任务,并且确保本次任务没有执行完时,下次任务不会执行。

在 Spring Boot 中,你可以使用 `@Scheduled` 注解来实现定时任务,同时结合 `ScheduledExecutorService` 或简单的标志位来确保任务在未完成时不会再次启动。下面是一个示例代码,展示了如何实现每隔 30 分钟执行一次任务,并且在任务未完成时不允许下次任务执行,同时在启动时立即执行一次任务。
### 步骤
#### 1. 创建 Spring Boot 项目
首先,确保你已经创建了一个 Spring Boot 项目。如果还没有,可以使用 Spring Initializr(https://start.spring.io/)来创建一个基本的 Spring Boot 项目,添加 `Spring Web` 和 `Spring Boot DevTools` 依赖。
#### 2. 配置定时任务
在 Spring Boot 项目中,你需要启用定时任务。可以通过在主应用类上添加 `@EnableScheduling` 注解来实现。
```java:src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
#### 3. 创建定时任务类
创建一个定时任务类,使用 `@Scheduled` 注解来定义任务的执行时间。同时,使用一个标志位来确保任务在未完成时不会再次启动。
```java:src/main/java/com/example/demo/ScheduledTask.java
package com.example.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class ScheduledTask {
private static final Logger logger = LoggerFactory.getLogger(ScheduledTask.class);
private boolean isTaskRunning = false;
public ScheduledTask() {
// 启动时立即执行一次任务
executeTask();
}
@Scheduled(fixedRate = 30 * 60 * 1000) // 每隔 30 分钟执行一次
public void scheduledTask() {
if (!isTaskRunning) {
executeTask();
}
}
private void executeTask() {
isTaskRunning = true;
try {
logger.info("任务开始执行: {}", getCurrentTime());
// 模拟任务执行,这里可以替换为实际的业务逻辑
Thread.sleep(10000); // 模拟任务执行 10 秒
logger.info("任务执行完成: {}", getCurrentTime());
} catch (InterruptedException e) {
logger.error("任务执行被中断", e);
} finally {
isTaskRunning = false;
}
}
private String getCurrentTime() {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
}
```
### 代码解释
1. **`@EnableScheduling` 注解**:在主应用类上添加该注解,启用 Spring Boot 的定时任务功能。
2. **`@Scheduled` 注解**:在 `scheduledTask` 方法上添加该注解,设置 `fixedRate = 30 * 60 * 1000`,表示每隔 30 分钟执行一次任务。
3. **`isTaskRunning` 标志位**:用于标记任务是否正在执行。在任务开始执行时将其设置为 `true`,任务执行完成后将其设置为 `false`。
4. **构造函数**:在 `ScheduledTask` 类的构造函数中调用 `executeTask` 方法,确保在应用启动时立即执行一次任务。
5. **`executeTask` 方法**:实际执行任务的方法,使用 `try-catch-finally` 块确保任务执行完成后将 `isTaskRunning` 标志位设置为 `false`。
### 运行项目
启动 Spring Boot 项目,你将看到任务在启动时立即执行一次,然后每隔 30 分钟执行一次。如果任务在 30 分钟内未完成,下次任务将不会启动。

完整代码 ScheduledTask.java 如下:
- package com.estar.wdserversyn.task;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- @Component
- public class ScheduledTask {
- private static final Logger logger = LoggerFactory.getLogger(ScheduledTask.class);
- private boolean isTaskRunning = false;
- public ScheduledTask() {
- // 启动时立即执行一次任务
- executeTask();
- }
- @Scheduled(fixedRateString = "${synconfig.fixedRate}")
- // @Scheduled(fixedRate = 1 * 60 * 1000) // 每隔 30 分钟执行一次
- public void preScheduledTask() {
- if (!isTaskRunning) {
- executeTask();
- }
- }
- private void executeTask() {
- isTaskRunning = true;
- try {
- // System.out.println("定时执行");
- logger.info("任务开始执行: {}", getCurrentTime());
- // 模拟任务执行,这里可以替换为实际的业务逻辑
- Thread.sleep(10000); // 模拟任务执行 10 秒
- logger.info("任务执行完成: {}", getCurrentTime());
- } catch (InterruptedException e) {
- logger.error("任务执行被中断", e);
- } finally {
- isTaskRunning = false;
- }
- }
- private String getCurrentTime() {
- return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
- }
- }
复制代码
|
|