spring boot框架开发入门实战(六)多线程与定时任务

多线程

使用Async注解启动线程

1. 使用方法

在启动类增加@EnableAsync注解,在需要执行的异步方法上加上@Async注解,@Async实际上就是多线程封装的

注:调用的方法与多线程的方法在同一个类中,此方式不生效

原因:类内部方法调用时,直接进行内部调用,没有走Spring的代理类。Async注解的实现都是基于Spring的AOP,而AOP的实现是基于动态代理模式实现的。调用方法的是对象本身而不是代理对象,没有经过Spring容器。

2. 必须要写在同一个类中的场景
方法1:懒加载注入

参考:SpringBoot @Async 注解无效_51CTO博客_springboot component注解

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
public class UserListController {
    // ...

    @Autowired
    @Lazy // 懒加载注入,不加会报错
    private UserListController userListController;

    @GetMapping("/user/queryAll")
    public ActionResult queryUserList() {
        List<UserList> users = userListService.queryAll();
        userListController.testSleep();     //调用
        return ActionResult.defaultOk(users);
    }

    @Async
    public void testSleep(){    // 需要多线程运行的函数
        try{
            log.info("等待中");
            Thread.sleep(10000);
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
方法2:先获取代理类

SpringBoot 注解@Async不生效的解决方法【异步处理】 - 菜鸟的奋斗之路 - 博客园 (cnblogs.com)

import org.springframework.context.ApplicationContext;

@Slf4j
@RestController
public class UserListController {
    // ...
    
    @Autowired
    private ApplicationContext applicationContext;

    @GetMapping("/user/queryAll")
    public ActionResult queryUserList() {
        List<UserList> users = userListService.queryAll();
        applicationContext.getBean(UserListController.class).testSleep();   //看这里
        return ActionResult.defaultOk(users);
    }

    @Async
    public void testSleep(){
        try{
            log.info("等待中");
            Thread.sleep(10000);
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
3. 分属于不同的类中的场景

正常注入和调用,比较简单,这里不再赘述。

定时任务

Scheduled注解

1. 使用方法

在入口类处加上@EnableScheduling注解,在定时任务的方法处加@Scheduled注解

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableAsync
@EnableScheduling
@SpringBootApplication
public class UamApplication {

	public static void main(String[] args) {
		SpringApplication.run(UamApplication.class, args);
	}

}
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
public class UserListController {
    @Scheduled(fixedDelay = 1000)
    public void testSchedule(){
        log.info("开始执行任务");
        try{
            log.info("等待3s中");
            Thread.sleep(3000);
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }
        log.info("执行任务完成");
    }
}

输出:

2023-04-13 17:17:17 [scheduling-1] INFO  com.jx.uam.controller.UserListController - 开始执行任务
2023-04-13 17:17:17 [scheduling-1] INFO  com.jx.uam.controller.UserListController - 等待3s中
2023-04-13 17:17:20 [scheduling-1] INFO  com.jx.uam.controller.UserListController - 执行任务完成
2023-04-13 17:17:21 [scheduling-1] INFO  com.jx.uam.controller.UserListController - 开始执行任务
2023-04-13 17:17:21 [scheduling-1] INFO  com.jx.uam.controller.UserListController - 等待3s中
2023-04-13 17:17:24 [scheduling-1] INFO  com.jx.uam.controller.UserListController - 执行任务完成

说明:该定时任务,每1s中触发一次,但每次执行时间为3秒,根据上面的输出,可以看出:此时是顺序执行的,如果需要异步执行,需要再加上@Async注解。

2. 异步调度
@Slf4j
@RestController
public class UserListController {
    @Async
    @Scheduled(fixedDelay = 1000)
    public void testSchedule(){
        log.info("开始执行任务");
        try{
            log.info("等待3s中");
            Thread.sleep(3000);
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }
        log.info("执行任务完成");
    }
}

输出:

2023-04-13 17:24:38 [task-1] INFO  com.jx.uam.controller.UserListController - 开始执行任务
2023-04-13 17:24:38 [task-1] INFO  com.jx.uam.controller.UserListController - 等待3s中
2023-04-13 17:24:39 [task-2] INFO  com.jx.uam.controller.UserListController - 开始执行任务
2023-04-13 17:24:39 [task-2] INFO  com.jx.uam.controller.UserListController - 等待3s中
2023-04-13 17:24:40 [task-3] INFO  com.jx.uam.controller.UserListController - 开始执行任务
2023-04-13 17:24:40 [task-3] INFO  com.jx.uam.controller.UserListController - 等待3s中
2023-04-13 17:24:41 [task-1] INFO  com.jx.uam.controller.UserListController - 执行任务完成
2023-04-13 17:24:41 [task-4] INFO  com.jx.uam.controller.UserListController - 开始执行任务
2023-04-13 17:24:41 [task-4] INFO  com.jx.uam.controller.UserListController - 等待3s中
2023-04-13 17:24:42 [task-2] INFO  com.jx.uam.controller.UserListController - 执行任务完成
3. Scheduled参数详解

SpringBoot定时任务 @Scheduled详解_爱吃耙土豆的博客-CSDN博客

SpringBoot使用@Scheduled注解实现定时任务_springboot 使用scheduled_pan_junbiao的博客-CSDN博客

在IDEA中,可以看到@Scheduled注解的参数有以下9项:

  • String cron() default “”

通过cron表达式定义规则,注意这里有七个参数。[秒] [分] [小时] [日] [月] [周] [年]

  • String zone() default “”

指定获取的时区,默认是空,表示使用服务器所在时区,比如Asia/BeiJingi或者Asia/Shanghai。

  • long fixedDelay() default -1L

定时任务执行完成之后再次执行定时任务的延时(需等待上次定时任务完成),单位毫秒

  • String fixedDelayString() default “”

与fixedDelay意思相同,只是使用字符串的形式。唯一不同的是可以支持占位符,可以在application.yml中定义数值,这里只用变量占位。例如:

# application.yml

time:
  fixedDelay: 5000
@Scheduled(fixedDelayString = "${time.fixedDelay}")
  • long fixedRate() default -1L

定时任务开始后再次执行定时任务的延时(需等待上次定时任务完成),单位毫秒

  • String fixedRateString() default “”

用法同fixedDelayString

  • long initialDelay() default -1L

表示第一次延迟多少毫秒执行,单位是毫秒

  • String initialDelayString() default “”

用法同fixedDelayString

  • TimeUnit timeUnit() default java.util.concurrent.TimeUnit.MILLISECONDS

默认时间单位是毫秒,可以通过timeUnit属性进行单位的设置,例如

@Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值