网易首页 > 网易号 > 正文 申请入驻

SpringBoot中Async异步方法和定时任务介绍

0
分享至

1.功能说明

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

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

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

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

2.关键注解和配置接口

功能开启注解:

EnableAsync和EnableScheduling

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

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

@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @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@EnableAsyncpublic class ThreadPoolBeanFactory extends AsyncConfigurerSupport{ @Override public 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); @Override public Thread newThread(Runnable r) { return new Thread(r, "Async-override-task-pool-thread-" + index.getAndIncrement()); } }); asyncTaskThreadPool.initialize(); return asyncTaskThreadPool; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { //返回值为void的异步方法不会传递异常,当方法中出现异常的时候只会打印日志,重写此方法来自定义异常处理方法 return null; }}

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

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

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

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

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

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

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

Async-task-pool-thread-1Async-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来实现返回值,定义如下:

@Async public Future{ 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"); }

asyncTaskWithResult()

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

单元测试代码如下:

@RunWith(SpringRunner.class)@SpringBootTestpublic class AsyncApplicationTests { @Autowired private AsyncTaskService asyncTaskService; @Test public void asyncTest() throws Exception{ Future

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:successasyncTask finished.

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
包工头与食堂大姐相好5年,项目完工提分开,这才意识到晚了

包工头与食堂大姐相好5年,项目完工提分开,这才意识到晚了

磊子讲史
2025-06-28 16:28:57
八村垒:快船给了我湖人所没有的东西

八村垒:快船给了我湖人所没有的东西

赛场速报局
2026-07-16 00:54:34
扳平英雄!恩佐:我在弧顶已经尝试好几脚了,我知道进球终会到来

扳平英雄!恩佐:我在弧顶已经尝试好几脚了,我知道进球终会到来

天光破云来
2026-07-16 11:55:04
中方奉陪到底!日舰借台风偷闯台海,被堵澎湖后,日媒集体哑火

中方奉陪到底!日舰借台风偷闯台海,被堵澎湖后,日媒集体哑火

古史青云啊
2026-07-15 09:42:02
不装了?美国财长放话,伊朗俄罗斯将回归美元体系,人民币该咋办

不装了?美国财长放话,伊朗俄罗斯将回归美元体系,人民币该咋办

超喜欢我
2026-07-16 00:41:35
女神的“全裸无删减”影片,值得收藏

女神的“全裸无删减”影片,值得收藏

来看美剧
2026-07-15 23:24:56
连续4天破亿,周星驰《功夫女足》成功超越刘德华《人潮汹涌》

连续4天破亿,周星驰《功夫女足》成功超越刘德华《人潮汹涌》

TVB的四小花
2026-07-15 12:52:12
深圳小伙娶回“神仙姐姐”?婚礼现场堪比偶像剧,网友:这是小说照进现实!

深圳小伙娶回“神仙姐姐”?婚礼现场堪比偶像剧,网友:这是小说照进现实!

曹莽看世界
2026-07-16 09:03:48
午评|科技大起大落!何时见底?A股明牌了!

午评|科技大起大落!何时见底?A股明牌了!

龙行天下虎
2026-07-16 11:48:12
“AI脸恐怖谷效应”再上热搜!生理性不适已成大众共识

“AI脸恐怖谷效应”再上热搜!生理性不适已成大众共识

新腕儿
2026-07-14 14:24:31
国台办:只要不从事违法犯罪,台胞可以高高兴兴来大陆平平安安回

国台办:只要不从事违法犯罪,台胞可以高高兴兴来大陆平平安安回

海峡导报社
2026-07-15 12:06:02
看完阿根廷2-1英格兰!不得不承认5个事实,梅西第9座金球稳了!

看完阿根廷2-1英格兰!不得不承认5个事实,梅西第9座金球稳了!

田先生篮球
2026-07-16 06:54:07
詹姆斯去向即将揭晓!美媒晒自由市场10条大鱼:湖人又锁定强援

詹姆斯去向即将揭晓!美媒晒自由市场10条大鱼:湖人又锁定强援

锅子篮球
2026-07-16 11:15:17
英媒:梅西跑动最高速度比卡塔尔世界杯涨约5%,47%时间在走动

英媒:梅西跑动最高速度比卡塔尔世界杯涨约5%,47%时间在走动

懂球帝
2026-07-15 13:48:02
广东废弃大学校园,昔日粤北最高学府,万人挤破头,如今人去楼空

广东废弃大学校园,昔日粤北最高学府,万人挤破头,如今人去楼空

糖逗在娱乐
2026-07-16 04:28:08
斯诺克新赛季第1冠来了:世锦赛亚军3-2终于夺生涯首冠,奖金30万

斯诺克新赛季第1冠来了:世锦赛亚军3-2终于夺生涯首冠,奖金30万

杨仔述
2026-07-16 04:45:31
黄晓明和田曦薇的新瓜,太大了!

黄晓明和田曦薇的新瓜,太大了!

美芽
2026-07-15 12:45:23
一夜消息:勇士无缘老詹,多队有意克莱,布伦森实至名归

一夜消息:勇士无缘老詹,多队有意克莱,布伦森实至名归

冷月小风风
2026-07-16 12:06:34
A股:紧急提醒2.5亿股民!从今天7月16日起,A股或可能迎黑色星期四?

A股:紧急提醒2.5亿股民!从今天7月16日起,A股或可能迎黑色星期四?

趋势清风侠
2026-07-16 09:52:14
央视40集扫黑大剧!孙红雷再演黑老大,王劲松助阵,爆款预定!

央视40集扫黑大剧!孙红雷再演黑老大,王劲松助阵,爆款预定!

东方不败然多多
2026-07-16 10:31:41
2026-07-16 12:47:00
伦点科技
伦点科技
分享最新智能科技资讯
35文章数 116962关注度
往期回顾 全部

科技要闻

SpaceX一度跌破发行价,较高点回落约40%

头条要闻

阿根廷FIFA积分登世界第一 阿根廷队长:这届太疯狂了

头条要闻

阿根廷FIFA积分登世界第一 阿根廷队长:这届太疯狂了

体育要闻

逆天6后卫神阵,图赫尔活活坑死英格兰

娱乐要闻

黄晓明回应赈灾车辆发生交通意外

财经要闻

长鑫科技批量造富:8名高管身家过亿

汽车要闻

零百加速1.96秒 腾势Z国内预售价68万起/四季度上市

态度原创

教育
亲子
数码
游戏
公开课

教育要闻

看了这3个进精神科的家庭,我决定换个思路养孩子……

亲子要闻

2026 入园准备:幼儿园午睡用什么睡袋

数码要闻

美光带来新选择!1γ LPDDR5X内存新增多个规格

《卧龙2:凤火连天》游民采访 战斗与地图全面进化

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版