SpringBoot之异步调用@Ansyc

简介: 本文介绍了在Spring Boot中实现异步任务的方法,通过在启动类或线程池配置类上添加`@EnableAsync`注解开启异步功能。详细说明了线程池属性类的定义,包括核心线程数、最大线程数、队列容量等参数配置。同时,文章指出需要在目标方法上使用`@Async`注解以实现异步执行,并列举了`@Async`注解失效的多种情况,如方法被`static`修饰、类未被Spring扫描、方法调用者与被调用方法在同一类中等。此外,还探讨了解决事务与异步之间矛盾的方案,强调了正确使用`@Transactional`注解的重要性。

在启动类或者线程池配置类上加注解 @EnableAsync

java

代码解读

复制代码

SpringBootApplication
// 开启异步执行
@EnableAsync
public class XFBlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(XFBlogApplication.class, args);
    }
}

定义了线程池的属性类

java

代码解读

复制代码

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * @className: ThreadPoolConfig
 * @description: 线程池配置
 * @author: change
 */
@Configuration
public class ThreadPoolConfig {

       /**
     * 核心线程池大小
     */
    public static final int  corePoolSize = 50;

    /**
     * 最大可创建的线程数
     */
    public static final int maxPoolSize = 200;

    /**
     * 队列最大长度
     */
    public static final int queueCapacity = 1000;

    /**
     * 线程池维护线程所允许的空闲时间
     */
    public static final int keepAliveSeconds = 300;

    /**
     * 线程池中的线程的名称前缀
     */
    public static final String threadNamePrefix = "async-thread-";

    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 1: 创建核心线程数 cpu核数 -- 50
        executor.setCorePoolSize(corePoolSize);
        // 2:线程池维护线程的最大数量,只有在缓存队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(maxPoolSize);
        // 3:缓存队列 可以写大一点无非就浪费一点内存空间
        executor.setQueueCapacity(queueCapacity);
        // 4:线程的空闲事件,当超过了核心线程数之外的线程在达到指定的空闲时间会被销毁 200ms
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 5:线程池中的线程的名称前缀
        executor.setThreadNamePrefix(threadNamePrefix);
        /* 当线程的任务缓存队列已满并且线程池中的线程数量已经达到了最大连接数,如果还有任务来就会采取拒绝策略,
         * 通常有四种策略:
         *ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出异常:RejectedExcutionException异常
         *ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常
         *ThreadPoolExecutor.DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
         *ThreadPoolExecutor.CallerRunsPolicy:重试添加当前的任务,自动重复调用execute()方法,直到成功。
         *ThreadPoolExecutor. 扩展重试3次,如果3次都不充公在移除。
         * */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}

需要异步的方法上面加上 @Async

java

代码解读

复制代码

@Component
public class Test {

    @Async("threadPoolTaskExecutor")
    public  void test(int i) throws Exception{
        System.out.println("线程名称: " + Thread.currentThread().getName());
        Thread.sleep(1000);
        System.out.println("参数:"+i);
    }
}

@Async注解失效的情况

arduino

  • 代码解读
  • 复制代码
异步方法使用static修饰。

less

  • 代码解读
  • 复制代码
异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类(因为@Async是spring的注解)。
  • 代码解读
  • 复制代码
异步方法不能与异步方法在同一个类中。

less

  • 代码解读
  • 复制代码
类中需要使用@Autowired@Resource等注解自动注入,不能自己手动new对象(就以上例来说,得注入service,而不能new)。

css

  • 代码解读
  • 复制代码
如果使用SpringBoot框架必须在启动类中/或者线程池固定属性类中,增加@EnableAsync注解。

java

  • 代码解读
  • 复制代码
在Async 方法上标注@Transactional是没用的。 在Async 方法调用的方法上标注@Transactional 有效。

css

  • 代码解读
  • 复制代码
调用被@Async标记的方法的调用者不能和被调用的方法在同一类中不然不会起作用。

css

  • 代码解读
  • 复制代码
使用@Async时要求是不能有返回值的不然会报错的 因为异步要求是不关心结果的。

解决事务和异步之间的矛盾

css

  • 代码解读
  • 复制代码
方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。

css

  • 代码解读
  • 复制代码
方法B,使用了@Async来标注, B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。


转载来源:https://juejin.cn/post/7112721946478903310

相关文章
|
9月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
570 0
|
Java 测试技术 Spring
Spring Boot使用@Async实现异步调用
Spring Boot使用@Async实现异步调用
105 0
|
前端开发 Java 关系型数据库
【SpringBoot】微服务学习笔记七:微服务中异步调用数据提交数据库的问题
【SpringBoot】微服务学习笔记七:微服务中异步调用数据提交数据库的问题
757 0
【SpringBoot】微服务学习笔记七:微服务中异步调用数据提交数据库的问题
|
Java Spring
使用spring boot的@Async实现异步调用和线程池复用
使用spring boot的@Async实现异步调用和线程池复用
982 0
使用spring boot的@Async实现异步调用和线程池复用
|
Java Spring
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
228 0
|
监控 Java
【十一】springboot整合异步调用并获取返回值
【十一】springboot整合异步调用并获取返回值
239 0
|
Java Spring
使用spring boot的@Async实现异步调用和线程池复用
使用spring boot的@Async实现异步调用和线程池复用
418 0
|
前端开发 Java 测试技术
SpringBoot-27- @Async实现异步调用 什么是异步调用
异步调用是相对于同步调用的,同步调用是按照顺序进行执行任务,只有上一个任务执行完成下一个任务才能执行,异步调用是指在按照顺序执行任务的过程中不需要等待任务结果的出现,就可以顺序执行下一个任务。
192 0
|
Java BI Spring
Srping注解之@Async:SpringBoot 实现异步调用
Srping注解之@Async:SpringBoot 实现异步调用
141 0
springboot多线程异步调用
在方法上添加@Async注解,在启动类添加@EnableAsync注解 controller