Spring中@Async用法总结

   在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题,本文将完成介绍@Async的用法。

  1.  何为异步调用?

    在解释异步调用之前,我们先来看同步调用的定义;同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。

     例如, 在某个调用中,需要顺序调用 A, B, C三个过程方法;如他们都是同步调用,则需要将他们都顺序执行完毕之后,方算作过程执行完毕; 如B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是执行开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了。

  2.  常规的异步调用处理方式

    在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。

  3. @Async介绍

   在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。

  如何在Spring中启用@Async

      4.线程池配置

    Spring应用默认的线程池,指在@Async注解在使用时,不指定线程池的名称。查看源码,@Async的默认线程池为SimpleAsyncTaskExecutor

@Configuration
@EnableAsync
public class ThreadPoolExecutorConfig {
	private Logger logger = LoggerFactory.getLogger(getClass());
	@Bean("taskExecutor")
	public Executor taskExecutor() {
		logger.info("初始化 taskExecutor");
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		// 配置核心线程数
		executor.setCorePoolSize(5);
		// 配置最大线程数
		executor.setMaxPoolSize(5);
		// 配置队列大小
		executor.setQueueCapacity(99999);
		// 配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("taskExecutor-");
		// rejection-policy:当pool已经达到max size的时候,如何处理新任务
		// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setKeepAliveSeconds(60);
        executor.setAwaitTerminationSeconds(60);
		// 执行初始化
		executor.initialize();
		return executor;
	}
}

  5.无返回值调用   

    基于@Async无返回值调用,直接在使用类,使用方法(建议在使用方法)上,加上注解。若需要抛出异常,需手动new一个异常抛出。

   /**
       * 带参数的异步调用 异步方法可以传入参数
       *  对于返回值是void,异常会被AsyncUncaughtExceptionHandler处理掉
       * @param s
       */
      @Async("taskExecutor")
      public void asyncInvokeWithException(String s) {
          log.info("asyncInvokeWithParameter, parementer={}", s);
          throw new IllegalArgumentException(s);
     }
  • 6.有返回值Future调用

  • /**
         * 异常调用返回Future
         *  对于返回值是Future,不会被AsyncUncaughtExceptionHandler处理,需要我们在方法中捕获异常并处理
         *  或者在调用方在调用Futrue.get时捕获异常进行处理
         * 
         * @param i
         * @return
         */
        @Async("taskExecutor")
        public Future<String> asyncInvokeReturnFuture(int i) {
            log.info("asyncInvokeReturnFuture, parementer={}", i);
            Future<String> future;
            try {
                Thread.sleep(1000 * 1);
                future = new AsyncResult<String>("success:" + i);
                throw new IllegalArgumentException("a");
            } catch (InterruptedException e) {
                future = new AsyncResult<String>("error");
            } catch(IllegalArgumentException e){
                future = new AsyncResult<String>("error-IllegalArgumentException");
            }
            return future;
        }

    关注小编微信公众号,有更多干货等你来拿
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值