1.功能说明

Spring提供了Async注解来实现方法的异步调用。
即当调用Async标识的方法时,调用线程不会等待被调用方法执行完成即返回继续执行以下操作,而被调用的方法则会启动一个独立线程来执行此方法

这种异步执行的方式通常用于处理接口中不需要返回给用户的数据处理。比如当注册的时候,只需要将用户信息返回用户,而关于信息的保存操作可以使用异步执行。

Spring提供了Scheduled注解来实现定时任务的功能。

在异步方法和定时任务功能中都是开发这自己定义需要执行的方法,然后交给Spring容器管理线程,并执行相应的方法。在使用异步方法和定时任务的时候需要特别注意的是线程池的配置以及任务中异常的处理。下面对这两个功能进行简单介绍。

2.关键注解和配置接口

功能开启注解:

EnableAsync和EnableScheduling

通过在Spring的配置类中添加这两个注解来开启Spring的异步方法和定时任务的功能

异步方法标识注解Async,其定义为:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {String value() default "";}

在注解定义中可以看到此注解可以用于type和method,当此注解用于类的时候,表示此类中的所有方法都为异步方法。此注解中的value属性可用于指定执行此异步方法的线程池。线程池的具体确定方法下面具体分析。

定时任务标识注解Scheduled,定义如下:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {定时任务String cron() default "";String zone() default "";//上次执行结束到下次执行开始long fixedDelay() default -1;String fixedDelayString() default "";上次执行开始到本次执行开始long fixedRate() default -1;fixedRate或者fixedDelay的时候第一次的延迟时间long initialDelay() default -1;}

3.Spring线程池的选择和自定义配置线程池

在项目中我们通常不会自己手动创建线程,而是通过统一的线程池来执行task或者异步方法,使用这种方法来避免多人团队中由于自定义线程导致的资源耗尽的问题。在自定义线程池之前首先要了解Spring在执行异步任务或者方法的时候是怎么选择线程池的。

3.1 Async对于线程池的选择顺序

Async线程池的选择顺序如下图所示:

Spring在执行async标识的异步方法的时候首先会在Spring的上下文中搜索类型为TaskExecutor或者名称为“taskExecutor”的bean,当可以找到的时候,就将任务提交到此线程池中执行。当不存在以上线程池的时候,Spring会手动创建一个SimpleAsyncTaskExecutor执行异步任务。

另外当标识async注解的时候指定了,value值,Spring会使用指定的线程池执行。比如以下:

@Async(value = "asyncTaskThreadPool")

这个时候Spring会去上下文中找名字为asyncTaskThreadPool的bean,并执行异步任务,找不到,会抛出异常。

3.2 Scheduled对于线程池的选择顺序

Scheduled对于线程池的选择顺序如下图所示:

当Spring执行定时任务的时候,首先会在上下文中找类型为TaskScheduler或者名称为taskScheduler的bean,找不到的时候会手动创建一个线程执行此task。

3.3 自定义线程池和异常处理

在了解了Spring对于线程池的选择后,我们需要自定义线程池。自定义Async线程池有三种方式。

方法一:首先配置接口,重写获取线程池的方法。

配置Async方法的线程池需要继承AsyncConfigurerSupport类,或者实现AsyncConfigurer接口,并重写getAsyncExecutor方法,代码如下:

@Configuration
@EnableAsync
public class ThreadPoolBeanFactory extends AsyncConfigurerSupport{@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor asyncTaskThreadPool = new ThreadPoolTaskExecutor();asyncTaskThreadPool.setCorePoolSize(100);asyncTaskThreadPool.setMaxPoolSize(200);asyncTaskThreadPool.setQueueCapacity(11);asyncTaskThreadPool.setThreadFactory(new ThreadFactory() {private final AtomicLong index = new AtomicLong(1);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, "Async-override-task-pool-thread-" + index.getAndIncrement());}});asyncTaskThreadPool.initialize();return asyncTaskThreadPool;}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {//返回值为void的异步方法不会传递异常,当方法中出现异常的时候只会打印日志,重写此方法来自定义异常处理方法return null;}
}

这种定义的方法缺点是没有定义bean。

方法二:自定义相应类型的线程池bean。

第二种方法是基于Spring对线程选择的原理来实现的,定义一个类型为TaskExecutor的bean,定义方式如下:

    @Beanpublic TaskExecutor asyncTaskThreadPool() {ThreadPoolTaskExecutor asyncTaskThreadPool = new ThreadPoolTaskExecutor();asyncTaskThreadPool.setCorePoolSize(100);asyncTaskThreadPool.setMaxPoolSize(200);asyncTaskThreadPool.setThreadFactory(new ThreadFactory() {private final AtomicLong index = new AtomicLong(1);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, "Async-task-pool-thread-" + index.getAndIncrement());}});// asyncTaskThreadPool.initialize();//当为bean的时候不需要调用此方法,装载容器的时候回自动调用return asyncTaskThreadPool;}

以上两种方式定义线程池的时候在定义异步方法可以不执行线程池。定义如下:

    @Asyncpublic void test(){System.out.println(Thread.currentThread().getName());}

此时Spring会自动使用以上定义的线程池执行此方法。使用以上两种配置输出结果依次是:

Async-task-pool-thread-1
Async-task-override-pool-thread-1

方法三 在Async注解中执行线程池名称

异步任务定义如下:

    @Async(value = "asyncTaskThreadPool")public void asyncTask2() {LOGGER.info("AsyncTask2 start.");LOGGER.info(Thread.currentThread().getName());LOGGER.info("AsyncTask2 finished.");}

此时Spring会在上下文中找名称为asyncTaskThreadPool的线程池来执行此任务。

类似的可以自定义Scheduled的线程池,需要实现的配置接口为:SchedulingConfigurer。方法类似。

4.Async返回操作结果

异步任务可以通过定义返回类型为Future来实现返回值,定义如下:

    @Asyncpublic Future<String> asyncTaskWithResult() {LOGGER.info("AsyncTaskWithResult start.");try {Thread.sleep(1000 * 10);} catch (Exception e) {return new AsyncResult<>("error" + e.getMessage());}LOGGER.info("AsyncTaskWithResult finished.");return new AsyncResult<>("success");}

5.编写单元测试测试功能

单元测试代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class AsyncApplicationTests {@Autowiredprivate AsyncTaskService asyncTaskService;@Testpublic void asyncTest() throws Exception{Future<String> future = asyncTaskService.asyncTaskWithResult();while (!future.isDone()) {System.out.println("Wait asyncTaskWithResult.");Thread.sleep(1000);}System.out.println("asyncTaskWithResult result is:" + future.get());System.out.println("asyncTask finished.");}}

输出内容如下:

Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
Wait asyncTaskWithResult.
AsyncTaskWithResult finished.
asyncTaskWithResult result is:success
asyncTask finished.

转载于:https://www.cnblogs.com/vitasyuan/p/9221250.html

SpringBoot中Async异步方法和定时任务介绍相关推荐

  1. @async注解_SpringBoot中Async异步方法和定时任务介绍

    1.功能说明 Spring提供了Async注解来实现方法的异步调用.即当调用Async标识的方法时,调用线程不会等待被调用方法执行完成即返回继续执行以下操作,而被调用的方法则会启动一个独立线程来执行此 ...

  2. async spring 默认线程池_SpringBoot中Async异步方法和定时任务介绍

    1.功能说明 Spring提供了Async注解来实现方法的异步调用.即当调用Async标识的方法时,调用线程不会等待被调用方法执行完成即返回继续执行以下操作,而被调用的方法则会启动一个独立线程来执行此 ...

  3. SpringBoot中使用异步方法优化Service逻辑,提高接口响应速度

    点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/weixin_43441509/ article/details/119855613 1. 为什么需要异步方法? 先说结论: 合 ...

  4. java quartz管理,SpringBoot中使用Quartz管理定时任务的方法

    定时任务在系统中用到的地方很多,例如每晚凌晨的数据备份,每小时获取第三方平台的 Token 信息等等,之前我们都是在项目中规定这个定时任务什么时候启动,到时间了便会自己启动,那么我们想要停止这个定时任 ...

  5. 在SpringBoot中优雅的实现定时任务

    在日常的项目开发中,往往会涉及到一些需要做到定时执行的代码,例如自动将超过24小时的未付款的单改为取消状态,自动将超过14天客户未签收的订单改为已签收状态等等,那么为了在Spring Boot中实现此 ...

  6. SpringBoot中使用定时器/开启定时任务

    1.启动类上添加@EnableScheduling注解 2.新建定时任务具体实现类 @Component public class RemindTime{//每隔10秒执行一次@Scheduled(c ...

  7. 【小家Spring】SpringBoot中使用Servlet、Filter、Listener三大组件的三种方式以及原理剖析

    每篇一句 要么就安逸的穷,要么就拼命的干 前提概要 web开发使用Controller基本能解决大部分的需求,但是有时候我们也需要使用Servlet,因为相对于拦截和监听来说,有时候原生的还是比较好用 ...

  8. SpringBoot中的定时任务的同步与异步

    SpringBoot中的定时任务的同步与异步你确定真的知道? 授人以渔 Java领域;架构知识;面试心得;互联网行业最新资讯 定时任务调度功能在我们的开发中是非常常见的,随便举几个例子:定时清除一些过 ...

  9. SpringBoot中定时任务与异步定时任务的实现

    场景 若依前后端分离版手把手教你本地搭建环境并运行项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662 在上面 ...

  10. hutool的定时任务不支持依赖注入怎么办_可调度定时任务在SpringBoot中的实践

    定时任务在我们的项目中或多或少都会使用到,不论你是初级程序员,还是有多年工作经验的中高级程序员,在项目中加一个定时任务去处理业务的一个aspect,为什么用了一个英文单词'aspect'?而不是'切面 ...

最新文章

  1. 强化学习,路在何方?
  2. 关于int main( int argc, char* argv[] ) 中arg和argv参数理解
  3. win10+anaconda安装tensorflow和keras遇到的坑小结
  4. TomCat使用以及端口号被占用的处理方法
  5. 工控蜜罐Conpot部署和入门及高级演变
  6. mysql8安装步骤及排坑
  7. Asp.net页面之间传递参数的几种方法
  8. Java多线程详解(线程不安全案例)
  9. java ssm 增删改查,Maven+SSM框架实现简单的增删改查
  10. HFSS阵列天线设计与仿真1
  11. python企业文档管理系统django
  12. java isbn_JAVA ISBN10 ISBN13 正则表达式
  13. 汇总15位身份证号和18位身份证号的区别
  14. Neo4j:一、CQL语句
  15. IDEA小游戏数字炸弹
  16. DJ编曲用什么软件,DJ编曲教需要哪些步骤
  17. 【c】分数类型的定义 c语言分数类型加减乘除的实现
  18. 互联网安全真正的守卫神
  19. CSS深度学习 - 文本方向 direction 和 dir
  20. Mldonkey的配置

热门文章

  1. 仿微信app项目流程
  2. tag untag_交换机该怎么理解Hybird中Tag和Untag端口模式?
  3. 小程序如何避免多次点击,重复触发事件
  4. 分布式 集群 负载均衡含义
  5. Yaf引入oss sdk
  6. Android远程过程通讯,Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析(3)...
  7. 全网首发:怎样制作CDKEY(7)-新思路
  8. jsweet-examples下载测试
  9. 代码管理学:一时不检查,工作必走样
  10. 编译ffmpeg,ffplay运行出错怎么办?