當(dāng)前位置:
首頁(yè) >
前端技术
> javascript
>内容正文
javascript
Spring及SpringBoot @Async配置步骤及注意事项
生活随笔
收集整理的這篇文章主要介紹了
Spring及SpringBoot @Async配置步骤及注意事项
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
- 前言
最近在做一個(gè)用戶(hù)反饋的功能,就是當(dāng)用戶(hù)反饋意見(jiàn)或建議后服務(wù)端將意見(jiàn)保存然后發(fā)郵件給相關(guān)模塊的開(kāi)發(fā)者。考慮發(fā)郵件耗時(shí)的情況所以我想用異步的方法去執(zhí)行,于是就開(kāi)始研究Spring的@Async了。但網(wǎng)上的許多教程都是相互抄襲且直接復(fù)制代碼的,根本沒(méi)有去自己實(shí)踐或者更改代碼,所以在這兩天我遇到了許多問(wèn)題,使得@Async無(wú)效,也一直沒(méi)有找到很好的文章去詳細(xì)的說(shuō)明@Async的正確及錯(cuò)誤的使用方法及需要注意的地方,這里Sring是以配置文件的形式來(lái)開(kāi)啟@Async,而SpringBoot則是以注解的方式開(kāi)啟。
- 教程
配置文件的話(huà)有兩種方式一種是精簡(jiǎn)式:
直接在applicationContext.xml中加入開(kāi)啟異步并添加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這樣好處是簡(jiǎn)單快速,缺點(diǎn)是線(xiàn)程池配置簡(jiǎn)單,線(xiàn)程創(chuàng)建不能定時(shí)關(guān)閉。
所以我推薦下面這種,定義一個(gè)線(xiàn)程池,然后引入。其實(shí)兩種方法原理是一樣只不過(guò)下面這種只是線(xiàn)程池配置更加詳細(xì),線(xiàn)程在空閑后會(huì)根據(jù)存活時(shí)間配置進(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"><!-- 開(kāi)啟異步,并引入線(xiàn)程池 --><task:annotation-driven executor="threadPool" /><!-- 定義線(xiàn)程池 --><bean id="threadPool"class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><!-- 核心線(xiàn)程數(shù),默認(rèn)為1 --><property name="corePoolSize" value="5" /><!-- 最大線(xiàn)程數(shù),默認(rèn)為Integer.MAX_VALUE --><property name="maxPoolSize" value="20" /><!-- 隊(duì)列最大長(zhǎng)度,一般需要設(shè)置值>=notifyScheduledMainExecutor.maxNum;默認(rèn)為Integer.MAX_VALUE --><property name="queueCapacity" value="500" /><!-- 線(xiàn)程池維護(hù)線(xiàn)程所允許的空閑時(shí)間,默認(rèn)為60s --><property name="keepAliveSeconds" value="30" /><!-- 完成任務(wù)自動(dòng)關(guān)閉 , 默認(rèn)為false--><property name="waitForTasksToCompleteOnShutdown" value="true" /><!-- 核心線(xiàn)程超時(shí)退出,默認(rèn)為false --><property name="allowCoreThreadTimeOut" value="true" /><!-- 線(xiàn)程池對(duì)拒絕任務(wù)(無(wú)線(xiàn)程可用)的處理策略,目前只支持AbortPolicy、CallerRunsPolicy;默認(rèn)為后者 --><property name="rejectedExecutionHandler"><!-- AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 --><!-- CallerRunsPolicy:主線(xiàn)程直接執(zhí)行該任務(wù),執(zhí)行完之后嘗試添加下一個(gè)任務(wù)到線(xiàn)程池中,可以有效降低向線(xiàn)程池內(nèi)添加任務(wù)的速度 --><!-- DiscardOldestPolicy:拋棄舊的任務(wù)、暫不支持;會(huì)導(dǎo)致被丟棄的任務(wù)無(wú)法再次被執(zhí)行 --><!-- DiscardPolicy:拋棄當(dāng)前任務(wù)、暫不支持;會(huì)導(dǎo)致被丟棄的任務(wù)無(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啟動(dòng)方式@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 注解必須要有,否則無(wú)法將此bean注入* 當(dāng)然也可以使用其他的注解,只要可以裝配就行* * @author chenmc* @date 2017年9月4日 下午3:38:29*/ @Component public class MyAsync {/*** @Async 表明這是一個(gè)異步方法,也就是說(shuō)當(dāng)調(diào)用這個(gè)方法時(shí),* spring會(huì)創(chuàng)建一條線(xiàn)程來(lái)執(zhí)行這個(gè)方法。* 注意:不能使用static來(lái)修飾此方法,否則@Async無(wú)效* * @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出來(lái)的對(duì)象@Async將無(wú)效,必須要spring注入的async.asyncMethod();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "end");}
這里總結(jié)一下@Async注解無(wú)效的可能點(diǎn)
一、異步方法使用static修飾
二、異步類(lèi)沒(méi)有使用@Component注解(或其他注解)導(dǎo)致spring無(wú)法掃描到異步類(lèi)
三、測(cè)試異步方法不能與異步方法在同一個(gè)類(lèi)中
四、測(cè)試類(lèi)中需要使用@Autowired或@Resource等注解自動(dòng)注入,不能自己手動(dòng)new對(duì)象
五、如果使用SpringBoot框架必須在啟動(dòng)類(lèi)中增加@EnableAsync注解
- 結(jié)語(yǔ)
spring的@Async真的極大的方便了java的異步(多線(xiàn)程)開(kāi)發(fā),心里默念三遍:感謝spring!感謝spring!感謝spring!
總結(jié)
以上是生活随笔為你收集整理的Spring及SpringBoot @Async配置步骤及注意事项的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SpringMVC+JWT+Swagge
- 下一篇: MySQL将utf8字符集改为utf8m