前言:

最近的时候遇到一个需求,就是当服务器接到请求并不需要任务执行完成才返回结果,可以立即返回结果,让任务异步的去执行。开始考虑是直接启一个新的线程去执行任务或者把任务提交到一个线程池去执行,这两种方法都是可以的。但是Spring 这么强大,肯定有什么更简单的方法,就 google 了一下,还真有呢。就是使用 @EnableAsync 和 @Async 这两个注解就 ok 了。

给方法加上 @Async 注解

package me.deweixu.aysncdemo.service;
public interface AsyncService {
void asyncMethod(String arg);
}
package me.deweixu.aysncdemo.service.ipml;
import me.deweixu.aysncdemo.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
@Async
@Override
public void asyncMethod(String arg) {
System.out.println("arg:" + arg);
System.out.println("=====" + Thread.currentThread().getName() + "=========");
}
}

@EnableAsync

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

package me.deweixu.aysncdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
public class AysncDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AysncDemoApplication.class, args);
}
}

测试

package me.deweixu.aysncdemo;
import me.deweixu.aysncdemo.service.AsyncService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class AysncDemoApplicationTests {
@Autowired
AsyncService asyncService;
@Test
public void testAsync() {
System.out.println("=====" + Thread.currentThread().getName() + "=========");
asyncService.asyncMethod("Async");
}
}
=====main=========
2018-03-25 21:30:31.391 INFO 28742 --- [ main] .s.a.AnnotationAsyncExecutionInterceptor : No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either
arg:Async
=====SimpleAsyncTaskExecutor-1=========

从上面的结果看 asyncService.asyncMethod("Async") 确实异步执行了,它使用了一个新的线程。

指定 "Executor"

从上面执行的日志可以猜测到 Spring 默认使用 SimpleAsyncTaskExecutor 来异步执行任务的,可以搜索到这个类。 @Async 也可以指定自定义的 Executor。

在启动类中增加自定义的 Executor

package me.deweixu.aysncdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@EnableAsync
@SpringBootApplication
public class AysncDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AysncDemoApplication.class, args);
}
@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
}

指定 "Executor"

package me.deweixu.aysncdemo.service.ipml;
import me.deweixu.aysncdemo.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
@Async("threadPoolTaskExecutor")
@Override
public void asyncMethod(String arg) {
System.out.println("arg:" + arg);
System.out.println("=====" + Thread.currentThread().getName() + "=========");
}
}

这样在异步执行任务的时候就使用 threadPoolTaskExecutor

设置默认的

Executor

上面提到如果 @Async 不指定 Executor 就默认使用 SimpleAsyncTaskExecutor,其实默认的 Executor 是可以使用 AsyncConfigurer 接口来配置的

@Configuration
public class SpringAsyncConfig implements AsyncConfigurer { @Override
public Executor getAsyncExecutor() {
return new ThreadPoolTaskExecutor();
} }

异常捕获

在异步执行的方法中是可能出现异常的,我们可以在任务内部使用 try catch 来处理异常,当任务抛出异常时, Spring 也提供了捕获它的方法。

实现 AsyncUncaughtExceptionHandler 接口

public class CustomAsyncExceptionHandler
implements AsyncUncaughtExceptionHandler { @Override
public void handleUncaughtException(
Throwable throwable, Method method, Object... obj) { System.out.println("Exception message - " + throwable.getMessage());
System.out.println("Method name - " + method.getName());
for (Object param : obj) {
System.out.println("Parameter value - " + param);
}
} }
实现 AsyncConfigurer 接口重写 getAsyncUncaughtExceptionHandler 方法
@Configuration
public class SpringAsyncConfig implements AsyncConfigurer { @Override
public Executor getAsyncExecutor() {
return new ThreadPoolTaskExecutor();
} @Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
} }

改写 asyncMethod 方法使它抛出异常

 @Async
@Override
public void asyncMethod(String arg) {
System.out.println("arg:" + arg);
System.out.println("=====" + Thread.currentThread().getName() + "=========");
throw new NullPointerException();
}

运行结果:

=====main=========
arg:Async
=====threadPoolTaskExecutor-1=========
Exception message - Async NullPointerException
Method name - asyncMethod
Parameter value - Async

正确捕获到了异常。

我是小架,我们

下篇文章见!

Spring Boot 之异步执行方法的更多相关文章

  1. Spring Boot Async异步执行

    异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑. 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下: Execut ...

  2. 使用spring的@Async异步执行方法

    应用场景: 1.某些耗时较长的而用户不需要等待该方法的处理结果 2.某些耗时较长的方法,后面的程序不需要用到这个方法的处理结果时 在spring的配置文件中加入对异步执行的支持 <beans x ...

  3. spring boot启动后执行方法

    @Componentpublic class InitProject implements ApplicationRunner { private static final Logger logger ...

  4. Spring boot 配置异步处理执行器

    示例如下: 1. 新建Maven 项目 async-executor 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

  5. 使用Spring Boot和AspectJ实现方法跟踪基础结构

    了解如何使用Spring Boot和AspectJ实现方法跟踪基础结构!最近在优锐课学习收获颇多,记录下来大家一起进步! 在我们的应用程序中,获取方法的堆栈跟踪信息可能会节省很多时间.具有输入输出参数 ...

  6. Spring Boot @Async 异步任务执行

    1.任务执行和调度 Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象. Spring的TaskExecutor和java.util.concurre ...

  7. Spring Boot 定时+多线程执行

    Spring Boot 定时任务有多种实现方式,我在一个微型项目中通过注解方式执行定时任务. 具体执行的任务,通过多线程方式执行,单线程执行需要1小时的任务,多线程下5分钟就完成了. 执行效率提升10 ...

  8. Spring Boot程序的执行流程

    Spring Boot的执行流程如下图所示:(图片来源于网络) 上图为SpringBoot启动结构图,我们发现启动流程主要分为三个部分,第一部分进行SpringApplication的初始化模块,配置 ...

  9. Spring Boot 初始化运行特定方法

    Spring Boot提供了两种 “开机自启动” 的方式,ApplicationRunner和CommandLineRunner 这两种方式的目的是为了满足,在容器启动时like执行某些方法.我们可以 ...

随机推荐

  1. 什么是单点登录,php是如何实现单点登录的

    单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...

  2. Github新项目Dress(好耶是女装)

    面向可爱的蓝孩子 (/ω\) 的 git 学习实践项目,包含了600多位蓝孩子的女装照,访问前做好心理准备. 每个人都可以成为这个项目的参与者 访问地址:https://github.com/kome ...

  3. (三十六)c#Winform自定义控件-步骤控件-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

  4. ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)

    在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口 ...

  5. Java中15种锁的分类综合总结

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  6. javaWeb技术第二篇之CSS、事件和案例

    <!--内联式 CSS (层叠样式表) 编辑 层叠样式表(英文全称:Cascading Style Sheets) CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式 ...

  7. SSM框架之Spring(5)JdbcTemplate及spring事务控制

    Spring(5)JdbcTemplate及spring事务控制 ##1.JdbcTmeplate 它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装.spring ...

  8. Vue.js2.0快速入门笔记

    vue.js 解耦视图与数据,可复用的组件,前端路由,状态管理,虚拟DOM. MVVM模式:当View(视图层)变化时,会自动更新ViewModel(视图模型),View与ViewModel之间双向绑 ...

  9. JS基础语法---Date对象---格式化日期

    格式化后的指定格式的日期和时间,封装一个函数 function getDate() { var dt = new Date(); var year = dt.getFullYear(); var mo ...

  10. oracle产销存的写法

    with TEMP as (select sum(MMT.TRANSACTION_QUANTITY) QTY_QC, MMT.INVENTORY_ITEM_ID --,CAH.Legal_Entity ...