Spring Boot延迟执行实现

news/2025/2/25 12:44:46

说明:本文介绍如何在Spring Boot项目中,延迟执行某方法,及讨论延迟执行方法的是事务问题。

搭建Demo

首先,创建一个Spring Boot项目,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/>
    </parent>

    <groupId>com.hezy</groupId>
    <artifactId>delay_thread_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>



        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
    </dependencies>
</project>

写个接口,打印进入方法时的时间

java">import com.hezy.service.DelayService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;

@RestController
@RequestMapping("/demo")
@Log4j2
public class DemoController {

    @Autowired
    private DelayService delayService;

    @GetMapping
    public String demo() {
        return "Hello World!";
    }

    @GetMapping("/delay1/{time}")
    public String delay1(@PathVariable Integer time) {
        log.info("enter delay1...date={} time={}",
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), time);
        delayService.delay1(time);
        return "success";
    }
}

延迟执行实现

delayService,delay1()实现,如下:

java">    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    /**
     * 延迟执行
     * @param time
     */
    public void delay1(Integer time) {
        scheduler.schedule(() -> {
            log.info("run delay1...date={} time={}",
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), time);
        }, time, TimeUnit.SECONDS);
    }

就是开了一个线程来执行,可设置延迟时间。启动项目,测试,如下:

(发送请求,响应结果即刻返回)

在这里插入图片描述

(控制台可见任务延迟5秒执行)

在这里插入图片描述

事务问题

写个实体类

java">import lombok.Data;

@Data
public class User {

    private Integer id;

    private String username;

    private String password;
}

再写个Mapper,里面写个insert()方法

java">import com.hezy.pojo.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {

    @Insert("insert into user (id, username, password) values (#{id}, #{username}, #{password})")
    void insert(User user);
}

新建个延迟方法,delay2(),方法生加声明式注解,方法内手动制造一个异常

(controller)

java">    @PostMapping("/delay2/{time}")
    public String delay2(@RequestBody User user, @PathVariable Integer time) {
        log.info("enter delay2...date={} time={}",
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), time);
        delayService.delay2(user, time);
        return "success";
    }

(service)

java">    /**
     * 声明式事务
     */
    @Transactional(rollbackFor = Exception.class)
    public void delay2(User user, Integer time) {
        scheduler.schedule(() -> {
            log.info("run delay2...date={} time={}",
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), time);
            userMapper.insert(user);
            
            int i = 1 / 0;
            
            user.setId(3);
            userMapper.insert(user);
        }, time, TimeUnit.SECONDS);
    }

启动项目,调用方法

在这里插入图片描述

控制台没有报错

在这里插入图片描述

数据库,插入了一条数据,事务没有控制住

在这里插入图片描述

以上说明,声明式事务无法控制延迟执行的方法,并且异常也被线程内捕获了,没有抛出来。

编程式事务

试下编程式事务,手动实现事务,如下:

(controller)

java">    @PostMapping("/delay3/{time}")
    public String delay3(@RequestBody User user, @PathVariable Integer time) {
        log.info("enter delay3...date={} time={}",
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), time);
        delayService.delay3(user, time);
        return "success";
    }

(service)

java">    @Autowired
    private PlatformTransactionManager transactionManager;

    /**
     * 编程式事务
     */
    public void delay3(User user, Integer time) {
        scheduler.schedule(() -> {
            TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
            try {
                log.info("run delay3...date={} time={}",
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), time);
                userMapper.insert(user);

                // 故意产生异常
                int i = 1 / 0;

                user.setId(3);
                userMapper.insert(user);

                // 提交事务
                transactionManager.commit(status);
            } catch (Exception e) {
                transactionManager.rollback(status);
                e.printStackTrace();
            }
        }, time, TimeUnit.SECONDS);
    }

把数据库记录删掉,启动项目,测试

在这里插入图片描述

控制台报错

在这里插入图片描述

数据库没有插入记录,编程式事务控制住了

在这里插入图片描述

总结

本文介绍了在Spring Boot项目中延迟执行方法的实现,以及延迟执行下声明式事务和编程式事务的使用情况。

完整源码:https://github.com/HeZhongYing/delay_thread_demo


http://www.niftyadmin.cn/n/5865516.html

相关文章

【数据结构进阶】哈希表

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;数据结构 目录 前言 一、哈希表的概念 二、哈希函数的实现方法 1. 直接定址法 2. 除留余数法 三、哈希冲突 1. 开放定址法&#xff08;闭散列&#xff0…

Vue.js组件开发:从基础到进阶

在现代前端开发中&#xff0c;Vue.js因其简洁、灵活和易上手的特点&#xff0c;成为了众多开发者首选的框架之一。组件化是Vue.js的核心思想之一&#xff0c;它让我们能够更高效、模块化地开发应用。在本文中&#xff0c;我们将从Vue.js的组件开发的基础知识开始&#xff0c;逐…

【Mysql】我在广州学Mysql 系列——Mysql 性能优化

ℹ️大家好&#xff0c;我是练小杰&#xff0c;今天又是美好的星期一了&#xff0c;新的工作又要开始了&#xff0c;努力&#xff01;&#xff01;奋斗&#xff01;&#xff01;&#x1f606; 本文是针对Mysql 性能优化知识进行学习与讨论&#xff0c;后续将添加更多相关知识噢…

【DeepSeek-R1背后的技术】系列十一:RAG原理介绍和本地部署(DeepSeekR1+RAGFlow构建个人知识库)

【DeepSeek-R1背后的技术】系列博文&#xff1a; 第1篇&#xff1a;混合专家模型&#xff08;MoE&#xff09; 第2篇&#xff1a;大模型知识蒸馏&#xff08;Knowledge Distillation&#xff09; 第3篇&#xff1a;强化学习&#xff08;Reinforcement Learning, RL&#xff09;…

uniapp 微信小程序打包之后vendor.js 主包体积太大,解决办法,“subPackages“:true设置不生效

现在是打包的时候&#xff0c;vendor.js 的内容全部打到了主包里面&#xff0c; 说一下我的方法&#xff1a; 1. 通过发行 小程序打包 这样打包的体积是最小的&#xff0c;打包之后打开微信开发工具&#xff0c;然后再上传 2.manifest.json,在“mp-weixin”里添加代码 "…

OpenHarmony-4.基于dayu800 GPIO 实践(2)

基于dayu800 GPIO 进行开发 1.DAYU800开发板硬件接口 LicheePi 4A 板载 2x10pin 插针&#xff0c;其中有 16 个原生 IO&#xff0c;包括 6 个普通 IO&#xff0c;3 对串口&#xff0c;一个 SPI。TH1520 SOC 具有4个GPIO bank&#xff0c;每个bank最大有32个IO&#xff1a;  …

开源神器KRR:用数据驱动K8s资源优化

引言:云原生时代的资源管理之痛 在Kubernetes集群中,过度配置导致资源浪费与配置不足引发稳定性风险的矛盾始终存在。CNCF调研显示,企业平均有35%的云资源处于闲置状态。本文将揭秘开源神器KRR(Kubernetes Resource Recommender),通过数据驱动方式实现精准资源配置,实测…

详解Tomcat下载安装以及IDEA配置Tomcat(2023最新)

目录 步骤一&#xff1a;首先确认自己是否已经安装JDK步骤二&#xff1a;下载安装Tomcat步骤三&#xff1a;Tomcat配置环境变量步骤四&#xff1a;验证Tomcat配置是否成功步骤五&#xff1a;为IDEA配置Tomcat 步骤一&#xff1a;首先确认自己是否已经安装JDK jdk各版本通用安…