當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring及SpringBoot @Async配置步骤及注意事项
生活随笔
收集整理的這篇文章主要介紹了
Spring及SpringBoot @Async配置步骤及注意事项
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
- 前言
最近在做一個用戶反饋的功能,就是當(dāng)用戶反饋意見或建議后服務(wù)端將意見保存然后發(fā)郵件給相關(guān)模塊的開發(fā)者。考慮發(fā)郵件耗時的情況所以我想用異步的方法去執(zhí)行,于是就開始研究Spring的@Async了。但網(wǎng)上的許多教程都是相互抄襲且直接復(fù)制代碼的,根本沒有去自己實踐或者更改代碼,所以在這兩天我遇到了許多問題,使得@Async無效,也一直沒有找到很好的文章去詳細(xì)的說明@Async的正確及錯誤的使用方法及需要注意的地方,這里Sring是以配置文件的形式來開啟@Async,而SpringBoot則是以注解的方式開啟。
- 教程
配置文件的話有兩種方式一種是精簡式:
直接在applicationContext.xml中加入開啟異步并添加task的命名空間
<task:executor id="WhifExecutor" pool-size="10"/> <task:annotation-driven executor="WhifExecutor" />xmlns:task="http://www.springframework.org/schema/task" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd這樣好處是簡單快速,缺點是線程池配置簡單,線程創(chuàng)建不能定時關(guān)閉。
所以我推薦下面這種,定義一個線程池,然后引入。其實兩種方法原理是一樣只不過下面這種只是線程池配置更加詳細(xì),線程在空閑后會根據(jù)存活時間配置進(jìn)行關(guān)閉。
在applicationContext.xml同目錄下創(chuàng)建文件threadPool.xml內(nèi)容如下,然后在applicationContext.xml中引入threadPool.xml:<import resource="threadPool.xml" />
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"><!-- 開啟異步,并引入線程池 --><task:annotation-driven executor="threadPool" /><!-- 定義線程池 --><bean id="threadPool"class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><!-- 核心線程數(shù),默認(rèn)為1 --><property name="corePoolSize" value="5" /><!-- 最大線程數(shù),默認(rèn)為Integer.MAX_VALUE --><property name="maxPoolSize" value="20" /><!-- 隊列最大長度,一般需要設(shè)置值>=notifyScheduledMainExecutor.maxNum;默認(rèn)為Integer.MAX_VALUE --><property name="queueCapacity" value="500" /><!-- 線程池維護(hù)線程所允許的空閑時間,默認(rèn)為60s --><property name="keepAliveSeconds" value="30" /><!-- 完成任務(wù)自動關(guān)閉 , 默認(rèn)為false--><property name="waitForTasksToCompleteOnShutdown" value="true" /><!-- 核心線程超時退出,默認(rèn)為false --><property name="allowCoreThreadTimeOut" value="true" /><!-- 線程池對拒絕任務(wù)(無線程可用)的處理策略,目前只支持AbortPolicy、CallerRunsPolicy;默認(rèn)為后者 --><property name="rejectedExecutionHandler"><!-- AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 --><!-- CallerRunsPolicy:主線程直接執(zhí)行該任務(wù),執(zhí)行完之后嘗試添加下一個任務(wù)到線程池中,可以有效降低向線程池內(nèi)添加任務(wù)的速度 --><!-- DiscardOldestPolicy:拋棄舊的任務(wù)、暫不支持;會導(dǎo)致被丟棄的任務(wù)無法再次被執(zhí)行 --><!-- DiscardPolicy:拋棄當(dāng)前任務(wù)、暫不支持;會導(dǎo)致被丟棄的任務(wù)無法再次被執(zhí)行 --><bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /></property></bean> </beans>
@EnableAsync @SpringBootApplication @ServletComponentScan @MapperScan("com.cmc.schedule.model.mapper") //配置掃描mapper接口的地址 public class NLPApplication extends SpringBootServletInitializer {//不使用springboot內(nèi)嵌tomcat啟動方式@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(NLPApplication.class);}public static void main(String[] args) {SpringApplication.run(NLPApplication.class, args);}//默認(rèn)使用fastjson解析@Beanpublic HttpMessageConverters fastJsonHttpMessageConverters() {FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);fastConverter.setFastJsonConfig(fastJsonConfig);HttpMessageConverter<?> converter = fastConverter;return new HttpMessageConverters(converter);} }
package com.cmc.tst;import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component;/*** @Component 注解必須要有,否則無法將此bean注入* 當(dāng)然也可以使用其他的注解,只要可以裝配就行* * @author chenmc* @date 2017年9月4日 下午3:38:29*/ @Component public class MyAsync {/*** @Async 表明這是一個異步方法,也就是說當(dāng)調(diào)用這個方法時,* spring會創(chuàng)建一條線程來執(zhí)行這個方法。* 注意:不能使用static來修飾此方法,否則@Async無效* * @author chenmc* @date 2017年9月4日 下午3:34:24*/@Asyncpublic void asyncMethod(){System.out.println(Thread.currentThread().getName());} }
@AutowiredMyAsync async;@Testpublic void test() {System.out.println(Thread.currentThread().getName() + "start");//MyAsync async = new MyAsync(); //自己new出來的對象@Async將無效,必須要spring注入的async.asyncMethod();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "end");}
這里總結(jié)一下@Async注解無效的可能點
一、異步方法使用static修飾
二、異步類沒有使用@Component注解(或其他注解)導(dǎo)致spring無法掃描到異步類
三、測試異步方法不能與異步方法在同一個類中
四、測試類中需要使用@Autowired或@Resource等注解自動注入,不能自己手動new對象
五、如果使用SpringBoot框架必須在啟動類中增加@EnableAsync注解
- 結(jié)語
spring的@Async真的極大的方便了java的異步(多線程)開發(fā),心里默念三遍:感謝spring!感謝spring!感謝spring!
總結(jié)
以上是生活随笔為你收集整理的Spring及SpringBoot @Async配置步骤及注意事项的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC+JWT+Swagge
- 下一篇: Spring Boot @Control