spring注解式异步实例

  1. 首先我们需要在调用异步方法的类型添加如下注解
@Configuration
@EnableAsync
  1. 然后再异步的方法上添加如下注解
@Async

这样就可以使用了

实例如下:

/**
 * 调到异步方法类
 */
@Configuration
@EnableAsync
public class PmZdfa extends Node{

	@Autowired
	private AsySendMsg asySendMsg;
	
	@Override
	public EnginResponse excute(EnginRequest enginRequest) {
	    
	    Thread thread = Thread.currentThread();
        System.out.println("================Thread: " + thread);
        System.out.println("================Thread Id: " + thread.getId());
        System.out.println("================Thread Name: " + thread.getName());
        System.out.println("================Thread Group: " + thread.getThreadGroup());
        System.out.println("================Thread Priority: " + thread.getPriority());
	    asySendMsg.sendMsg();
}

/**
 * 异步方法具体实现
 */
@Component("asySendMsg")
public class AsySendMsg {
    
    @Autowired
    private ISysMsgInterface iSysMsgInterface;
    
    @Async
    public void sendMsg(){
        Thread thread = Thread.currentThread();
        System.out.println("================Thread: " + thread);
        System.out.println("================Thread Id: " + thread.getId());
        System.out.println("================Thread Name: " + thread.getName());
        System.out.println("================Thread Group: " + thread.getThreadGroup());
        System.out.println("================Thread Priority: " + thread.getPriority());
    }
}


//控制台输出:
================Thread: Thread[DubboServerHandler-10.40.231.184:20985-thread-19,5,main]
================Thread Id: 59
================Thread Name: DubboServerHandler-10.40.231.184:20985-thread-19
================Thread Group: java.lang.ThreadGroup[name=main,maxpri=10]
================Thread Priority: 5
================Thread: Thread[SimpleAsyncTaskExecutor-1,5,main]
================Thread Id: 60
================Thread Name: SimpleAsyncTaskExecutor-1
================Thread Group: java.lang.ThreadGroup[name=main,maxpri=10]
================Thread Priority: 5

@Async默认异步配置使用的是SimpleAsyncTaskExecutor,该线程池默认来一个任务创建一个线程,若系统中不断的创建线程,最终会导致系统占用内存过高,引发OutOfMemoryError错误。针对线程创建问题,SimpleAsyncTaskExecutor提供了限流机制,通过concurrencyLimit属性来控制开关,当concurrencyLimit>=0时开启限流机制,默认关闭限流机制即concurrencyLimit=-1,当关闭情况下,会不断创建新的线程来处理任务。基于默认配置,SimpleAsyncTaskExecutor并不是严格意义的线程池,达不到线程复用的功能。

@Async应用自定义线程池

自定义线程池,可对系统中线程池更加细粒度的控制,方便调整线程池大小配置,线程执行异常控制和处理。在设置系统自定义线程池代替默认线程池时,虽可通过多种模式设置,但替换默认线程池最终产生的线程池有且只能设置一个(不能设置多个类继承AsyncConfigurer)自定义线程池有如下模式:

  1. 重新实现接口AsyncConfigurer
  2. 继承AsyncConfigurerSupport
  3. 配置由自定义的TaskExecutor替代内置的任务执行器

通过查看Spring源码关于@Async的默认调用规则,会优先查询源码中实现AsyncConfigurer这个接口的类,实现这个接口的类为AsyncConfigurerSupport。但默认配置的线程池和异步处理方法均为空,所以,无论是继承或者重新实现接口,都需指定一个线程池。且重新实现 public Executor getAsyncExecutor()方法。

1.实现接口AsyncConfigurer
在这里插入图片描述
2.继承AsyncConfigurerSupport
在这里插入图片描述
3.配置自定义的TaskExecutor

由于AsyncConfigurer的默认线程池在源码中为空,Spring通过beanFactory.getBean(TaskExecutor.class)先查看是否有线程池,未配置时,通过beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class),又查询是否存在默认名称为TaskExecutor的线程池。

所以可在项目中,定义名称为TaskExecutor的bean生成一个默认线程池。也可不指定线程池的名称,申明一个线程池,本身底层是基于TaskExecutor.class便可。

比如:

Executor.class:ThreadPoolExecutorAdapter->ThreadPoolExecutor->AbstractExecutorService->ExecutorService->Executor

这样的模式,最终底层为Executor.class,在替换默认的线程池时,需设置默认的线程池名称为TaskExecutor

TaskExecutor.class:ThreadPoolTaskExecutor->SchedulingTaskExecutor->AsyncTaskExecutor->TaskExecutor

这样的模式,最终底层为TaskExecutor.class,在替换默认的线程池时,可不指定线程池名称。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值