SpringBoot中使用多線(xiàn)程的方法示例
一、介紹
Spring是通過(guò)任務(wù)執(zhí)行器(TaskExecutor)來(lái)實(shí)現(xiàn)多線(xiàn)程和并發(fā)編程,使用Spring提供的ThreadPoolTaskExecutor來(lái)創(chuàng)建一個(gè)基于線(xiàn)城池的TaskExecutor。在使用線(xiàn)程池的大多數(shù)情況下都是異步非阻塞的。節(jié)省更多的時(shí)間,提高效率。
工作原理

當(dāng)主線(xiàn)程中調(diào)用execute接口提交執(zhí)行任務(wù)時(shí):則執(zhí)行以下步驟:注意:線(xiàn)程池初始時(shí),是空的。
- 如果當(dāng)前線(xiàn)程數(shù)<corePoolSize,如果是則創(chuàng)建新的線(xiàn)程執(zhí)行該任務(wù)
- 如果當(dāng)前線(xiàn)程數(shù)>=corePoolSize,則將任務(wù)存入BlockingQueue
- 如果阻塞隊(duì)列已滿(mǎn),且當(dāng)前線(xiàn)程數(shù)<maximumPoolSize,則新建線(xiàn)程執(zhí)行該任務(wù)。
- 如果阻塞隊(duì)列已滿(mǎn),且當(dāng)前線(xiàn)程數(shù)>=maximumPoolSize,則拋出異常RejectedExecutionException,告訴調(diào)用者無(wú)法再接受任務(wù)了。
在Springboot中對(duì)其進(jìn)行了簡(jiǎn)化處理,只需要配置一個(gè)類(lèi)型為java.util.concurrent.TaskExecutor或其子類(lèi)的bean,并在配置類(lèi)或直接在程序入口類(lèi)上聲明注解@EnableAsync,即可可以開(kāi)啟異步任務(wù)。
調(diào)用也簡(jiǎn)單,在由Spring管理的對(duì)象的方法上標(biāo)注注解@Async,聲明是異步任務(wù),顯式調(diào)用即可生效。
二、聲明
讓配置類(lèi)實(shí)現(xiàn)AsyncConfigurer接口,并重寫(xiě)getAsyncExecutor方法,并返回一個(gè)ThreasPoolTaskExecutor,就可以獲取一個(gè)基于線(xiàn)程池的TaskExecutor
使用注解@EnableAsync開(kāi)啟異步,會(huì)自動(dòng)掃描
@Configuration
@EnableAsync
public class ThreadConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(15);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
三、調(diào)用
通過(guò)@Async注解表明該方法是異步方法,如果注解在類(lèi)上,那表明這個(gè)類(lèi)里面的所有方法都是異步的
@Service
public class AsyncTaskService {
@Async
public void executeAsyncTask(int i) {
System.out.println("線(xiàn)程" + Thread.currentThread().getName() + " 執(zhí)行異步任務(wù):" + i);
}
}
四、進(jìn)階
有時(shí)候我們不止希望異步執(zhí)行任務(wù),還希望任務(wù)執(zhí)行完成后會(huì)有一個(gè)返回值,在java中提供了Future泛型接口,用來(lái)接收任務(wù)執(zhí)行結(jié)果,springboot也提供了此類(lèi)支持,使用實(shí)現(xiàn)了ListenableFuture接口的類(lèi)如AsyncResult來(lái)作為返回值的載體。比如上例中,我們希望返回一個(gè)類(lèi)型為String類(lèi)型的值,可以將返回值改造為:
@Async
public Future<String> executeAsyncTaskWithResult2(int i) {
System.out.println("線(xiàn)程" + Thread.currentThread().getName() + " 開(kāi)始執(zhí)行異步任務(wù)" + i);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線(xiàn)程" + Thread.currentThread().getName() + " 結(jié)束執(zhí)行異步任務(wù)" + i);
return new AsyncResult<>("線(xiàn)程" + Thread.currentThread().getName() + " 執(zhí)行異步任務(wù):" + i);
}
調(diào)用返回值:
get()是阻塞式,等待當(dāng)前線(xiàn)程完成才返回值
public void threadTest() {
try {
List<Future> futures = new ArrayList<>();
for (int i = 0; i < 20; i++) {
futures.add(asyncTaskService.executeAsyncTaskWithResult2(i));
}
// 獲取值。get是阻塞式,等待當(dāng)前線(xiàn)程完成才返回值
for (Future<String> future : futures) {
System.out.println("返回結(jié)果:" + future.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
補(bǔ)充
實(shí)際上,@Async還有一個(gè)參數(shù),通過(guò)Bean名稱(chēng)來(lái)指定調(diào)用的線(xiàn)程池-比如上例中設(shè)置的線(xiàn)程池參數(shù)不滿(mǎn)足業(yè)務(wù)需求,可以另外定義合適的線(xiàn)程池,調(diào)用時(shí)指明使用這個(gè)線(xiàn)程池-缺省時(shí)springboot會(huì)優(yōu)先使用名稱(chēng)為'taskExecutor'的線(xiàn)程池,如果沒(méi)有找到,才會(huì)使用其他類(lèi)型為T(mén)askExecutor或其子類(lèi)的線(xiàn)程池。
到此這篇關(guān)于SpringBoot中使用多線(xiàn)程的方法示例的文章就介紹到這了,更多相關(guān)SpringBoot使用多線(xiàn)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用正則表達(dá)式去除小數(shù)點(diǎn)后面多余的0功能示例
這篇文章主要介紹了Java使用正則表達(dá)式去除小數(shù)點(diǎn)后面多余的0功能,結(jié)合具體實(shí)例形式分析了java字符串正則替換相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
Spring?Boot項(xiàng)目中解決跨域問(wèn)題的四種方式總結(jié)
這篇文章主要介紹了瀏覽器同源策略限制導(dǎo)致的跨域問(wèn)題,并詳細(xì)記錄了常見(jiàn)的跨域解決方案,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02
Mybatis-Plus將字段設(shè)置為null解決方法
MyBatis-Plus是一個(gè)MyBatis的增強(qiáng)工具,在MyBatis的基礎(chǔ)上只做增 強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生,下面這篇文章主要給大家介紹了關(guān)于Mybatis-Plus將字段設(shè)置為null的解決方法的相關(guān)資料,需要的朋友可以參考下2023-04-04
Spring Boot整合JPA使用多個(gè)數(shù)據(jù)源的方法步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot整合JPA使用多個(gè)數(shù)據(jù)源的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
java后臺(tái)實(shí)現(xiàn)支付寶支付接口和支付寶訂單查詢(xún)接口(前端為APP)
這篇文章主要介紹了java后臺(tái)實(shí)現(xiàn)支付寶支付接口和支付寶訂單查詢(xún)接口(前端為APP),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-08-08
mybatis如何使用注解實(shí)現(xiàn)一對(duì)多關(guān)聯(lián)查詢(xún)
這篇文章主要介紹了mybatis如何使用注解實(shí)現(xiàn)一對(duì)多關(guān)聯(lián)查詢(xún)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot?AOP中JoinPoint的使用方式和通知切點(diǎn)表達(dá)式
這篇文章主要介紹了SpringBoot?AOP中JoinPoint的使用方式和通知切點(diǎn)表達(dá)式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
使用Java8實(shí)現(xiàn)觀察者模式的方法(上)
本文給大家介紹使用java8實(shí)現(xiàn)觀察者模式的方法,涉及到j(luò)ava8觀察者模式相關(guān)知識(shí),對(duì)此感興趣的朋友一起學(xué)習(xí)吧2016-02-02
Java手寫(xiě)Redis服務(wù)端的實(shí)現(xiàn)
本文主要介紹了Java手寫(xiě)Redis服務(wù)端的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12

