前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot之异步调用@Ansyc

SpringBoot之异步调用@Ansyc

作者头像
用户10125653
发布2022-11-10 21:55:30
4020
发布2022-11-10 21:55:30
举报
文章被收录于专栏:changechange

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

代码语言:javascript
复制
SpringBootApplication
// 开启异步执行
@EnableAsync
public class XFBlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(XFBlogApplication.class, args);
    }
}

定义了线程池的属性类

代码语言:javascript
复制
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

代码语言:javascript
复制
@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注解失效的情况

代码语言:javascript
复制
异步方法使用static修饰。
代码语言:javascript
复制
异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类(因为@Async是spring的注解)。
代码语言:javascript
复制
异步方法不能与异步方法在同一个类中。
代码语言:javascript
复制
类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象(就以上例来说,得注入service,而不能new)。
代码语言:javascript
复制
如果使用SpringBoot框架必须在启动类中/或者线程池固定属性类中,增加@EnableAsync注解。
代码语言:javascript
复制
在Async 方法上标注@Transactional是没用的。 在Async 方法调用的方法上标注@Transactional 有效。
代码语言:javascript
复制
调用被@Async标记的方法的调用者不能和被调用的方法在同一类中不然不会起作用。
代码语言:javascript
复制
使用@Async时要求是不能有返回值的不然会报错的 因为异步要求是不关心结果的。

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

代码语言:javascript
复制
方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。
代码语言:javascript
复制
方法B,使用了@Async来标注, B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在启动类或者线程池配置类上加注解 @EnableAsync
  • 定义了线程池的属性类
  • 需要异步的方法上面加上 @Async
  • @Async注解失效的情况
  • 解决事务和异步之间的矛盾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档