SpringBoot使用多线程注解@async

本文探讨了SpringBoot中@Async注解的正确使用方法,分析了直接调用与通过Spring管理Bean调用的区别,揭示了注解失效的常见原因,并提供了有效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.主类

import com.cnczsq.mall.elephant.utils.SpringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author : zhang sq
 * @date : 2019/10/8 11:24
 * SpringBoot注解多线程
 **/
@RestController
@RequestMapping("/AsyncTest")
@Api(value = "注解多线程测试", description = "AsyncTest")
public class AsyncTest {
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private Asyncs asyncs;

    @GetMapping("/test")
    @ApiOperation(value = "线程测试")
    @Transactional
    public String test() {
        //直接调用失效,为单线程
        doAsyncMethod();
        doAsyncMethod();
        doAsyncMethod();
        doAsyncMethod();
        doAsyncMethod();

        //从写类单独管理 ,注入调用,多线程
        asyncs.doAsyncMethod();
        asyncs.doAsyncMethod();
        asyncs.doAsyncMethod();
        asyncs.doAsyncMethod();
        asyncs.doAsyncMethod();

        //内部调用,通过获取bean对象,调用,多线程
        AsyncTest bean = SpringUtils.getBean(AsyncTest.class);
        bean.doAsyncMethod();
        bean.doAsyncMethod();
        bean.doAsyncMethod();
        bean.doAsyncMethod();
        bean.doAsyncMethod();
        log.info("主线程执行结束......");
        return "SUCCESS";
    }

    /**
     * @Description //同类方法中的异步标签
     **/
    @Async
    public void doAsyncMethod() {
        try {
            Thread.sleep(2000);
            log.info("2直接调用类异步方法执行了......");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.单独管理线程,注入类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
 * @author : zhang sq
 * @date : 2019/10/8 11:26
 **/
@Component
public class Asyncs {
    private  final Logger log =  LoggerFactory.getLogger(this.getClass());
    @Async
    public void doAsyncMethod() {
        try {
            Thread.sleep(2000);
            log.info("1注入类异步方法执行了......");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3.SpringUtil工具类,获取spring管理bean

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
 * @author : zhang sq
 * @date : 2019/8/30 17:17
 **/
@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtils.applicationContext == null) {
            SpringUtils.applicationContext = applicationContext;
        }
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

4.测试结果

结果:直接在类里面调用,为单线程处理@Async 不生效 , 可以使用单独管理线程注入调用,或者获取spring管理的Bean对象,调用,都可以达到异步效果;

常见@Async注解不生效原因:

    1.@SpringBootApplication启动类当中没有添加注解@EnableAsync注解。

    2.没有走Spring的代理类。因为@Transactional和@Async注解的实现都是基于Spring的AOP,而AOP的实现是基于动态代理模式实现的。那么注解失效的原因就很明显了,有可能因为调用方法的是对象本身而不是代理对象,因为没有经过Spring容器

    3.还有一种说法是 异步方法使用注解@Async的返回值只能为void或者Future。我测试好像不存在这个问题(待定)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值