當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring及SpringBoot @Async配置步骤及注意事项
生活随笔
收集整理的這篇文章主要介紹了
Spring及SpringBoot @Async配置步骤及注意事项
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
- 前言
最近在做一個用戶反饋的功能,就是當用戶反饋意見或建議后服務端將意見保存然后發郵件給相關模塊的開發者。考慮發郵件耗時的情況所以我想用異步的方法去執行,于是就開始研究Spring的@Async了。但網上的許多教程都是相互抄襲且直接復制代碼的,根本沒有去自己實踐或者更改代碼,所以在這兩天我遇到了許多問題,使得@Async無效,也一直沒有找到很好的文章去詳細的說明@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這樣好處是簡單快速,缺點是線程池配置簡單,線程創建不能定時關閉。
所以我推薦下面這種,定義一個線程池,然后引入。其實兩種方法原理是一樣只不過下面這種只是線程池配置更加詳細,線程在空閑后會根據存活時間配置進行關閉。
在applicationContext.xml同目錄下創建文件threadPool.xml內容如下,然后在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"><!-- 核心線程數,默認為1 --><property name="corePoolSize" value="5" /><!-- 最大線程數,默認為Integer.MAX_VALUE --><property name="maxPoolSize" value="20" /><!-- 隊列最大長度,一般需要設置值>=notifyScheduledMainExecutor.maxNum;默認為Integer.MAX_VALUE --><property name="queueCapacity" value="500" /><!-- 線程池維護線程所允許的空閑時間,默認為60s --><property name="keepAliveSeconds" value="30" /><!-- 完成任務自動關閉 , 默認為false--><property name="waitForTasksToCompleteOnShutdown" value="true" /><!-- 核心線程超時退出,默認為false --><property name="allowCoreThreadTimeOut" value="true" /><!-- 線程池對拒絕任務(無線程可用)的處理策略,目前只支持AbortPolicy、CallerRunsPolicy;默認為后者 --><property name="rejectedExecutionHandler"><!-- AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 --><!-- CallerRunsPolicy:主線程直接執行該任務,執行完之后嘗試添加下一個任務到線程池中,可以有效降低向線程池內添加任務的速度 --><!-- DiscardOldestPolicy:拋棄舊的任務、暫不支持;會導致被丟棄的任務無法再次被執行 --><!-- DiscardPolicy:拋棄當前任務、暫不支持;會導致被丟棄的任務無法再次被執行 --><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內嵌tomcat啟動方式@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(NLPApplication.class);}public static void main(String[] args) {SpringApplication.run(NLPApplication.class, args);}//默認使用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注入* 當然也可以使用其他的注解,只要可以裝配就行* * @author chenmc* @date 2017年9月4日 下午3:38:29*/ @Component public class MyAsync {/*** @Async 表明這是一個異步方法,也就是說當調用這個方法時,* spring會創建一條線程來執行這個方法。* 注意:不能使用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");}
這里總結一下@Async注解無效的可能點
一、異步方法使用static修飾
二、異步類沒有使用@Component注解(或其他注解)導致spring無法掃描到異步類
三、測試異步方法不能與異步方法在同一個類中
四、測試類中需要使用@Autowired或@Resource等注解自動注入,不能自己手動new對象
五、如果使用SpringBoot框架必須在啟動類中增加@EnableAsync注解
- 結語
spring的@Async真的極大的方便了java的異步(多線程)開發,心里默念三遍:感謝spring!感謝spring!感謝spring!
總結
以上是生活随笔為你收集整理的Spring及SpringBoot @Async配置步骤及注意事项的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC+JWT+Swagge
- 下一篇: gradle idea java ssm