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

當主線程中調用execute接口提交執(zhí)行任務時:則執(zhí)行以下步驟:注意:線程池初始時,是空的。
- 如果當前線程數(shù)<corePoolSize,如果是則創(chuàng)建新的線程執(zhí)行該任務
- 如果當前線程數(shù)>=corePoolSize,則將任務存入BlockingQueue
- 如果阻塞隊列已滿,且當前線程數(shù)<maximumPoolSize,則新建線程執(zhí)行該任務。
- 如果阻塞隊列已滿,且當前線程數(shù)>=maximumPoolSize,則拋出異常RejectedExecutionException,告訴調用者無法再接受任務了。
在Springboot中對其進行了簡化處理,只需要配置一個類型為java.util.concurrent.TaskExecutor或其子類的bean,并在配置類或直接在程序入口類上聲明注解@EnableAsync,即可可以開啟異步任務。
調用也簡單,在由Spring管理的對象的方法上標注注解@Async,聲明是異步任務,顯式調用即可生效。
二、聲明
讓配置類實現(xiàn)AsyncConfigurer接口,并重寫getAsyncExecutor方法,并返回一個ThreasPoolTaskExecutor,就可以獲取一個基于線程池的TaskExecutor
使用注解@EnableAsync開啟異步,會自動掃描
@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;
}
}
三、調用
通過@Async注解表明該方法是異步方法,如果注解在類上,那表明這個類里面的所有方法都是異步的
@Service
public class AsyncTaskService {
@Async
public void executeAsyncTask(int i) {
System.out.println("線程" + Thread.currentThread().getName() + " 執(zhí)行異步任務:" + i);
}
}
四、進階
有時候我們不止希望異步執(zhí)行任務,還希望任務執(zhí)行完成后會有一個返回值,在java中提供了Future泛型接口,用來接收任務執(zhí)行結果,springboot也提供了此類支持,使用實現(xiàn)了ListenableFuture接口的類如AsyncResult來作為返回值的載體。比如上例中,我們希望返回一個類型為String類型的值,可以將返回值改造為:
@Async
public Future<String> executeAsyncTaskWithResult2(int i) {
System.out.println("線程" + Thread.currentThread().getName() + " 開始執(zhí)行異步任務" + i);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程" + Thread.currentThread().getName() + " 結束執(zhí)行異步任務" + i);
return new AsyncResult<>("線程" + Thread.currentThread().getName() + " 執(zhí)行異步任務:" + i);
}
調用返回值:
get()是阻塞式,等待當前線程完成才返回值
public void threadTest() {
try {
List<Future> futures = new ArrayList<>();
for (int i = 0; i < 20; i++) {
futures.add(asyncTaskService.executeAsyncTaskWithResult2(i));
}
// 獲取值。get是阻塞式,等待當前線程完成才返回值
for (Future<String> future : futures) {
System.out.println("返回結果:" + future.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
補充
實際上,@Async還有一個參數(shù),通過Bean名稱來指定調用的線程池-比如上例中設置的線程池參數(shù)不滿足業(yè)務需求,可以另外定義合適的線程池,調用時指明使用這個線程池-缺省時springboot會優(yōu)先使用名稱為'taskExecutor'的線程池,如果沒有找到,才會使用其他類型為TaskExecutor或其子類的線程池。
到此這篇關于SpringBoot中使用多線程的方法示例的文章就介紹到這了,更多相關SpringBoot使用多線程內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java使用正則表達式去除小數(shù)點后面多余的0功能示例
這篇文章主要介紹了Java使用正則表達式去除小數(shù)點后面多余的0功能,結合具體實例形式分析了java字符串正則替換相關操作技巧,需要的朋友可以參考下2017-06-06
Spring Boot整合JPA使用多個數(shù)據(jù)源的方法步驟
這篇文章主要給大家介紹了關于Spring Boot整合JPA使用多個數(shù)據(jù)源的方法步驟,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring Boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-08-08
java后臺實現(xiàn)支付寶支付接口和支付寶訂單查詢接口(前端為APP)
這篇文章主要介紹了java后臺實現(xiàn)支付寶支付接口和支付寶訂單查詢接口(前端為APP),非常具有實用價值,需要的朋友可以參考下2018-08-08
mybatis如何使用注解實現(xiàn)一對多關聯(lián)查詢
這篇文章主要介紹了mybatis如何使用注解實現(xiàn)一對多關聯(lián)查詢的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot?AOP中JoinPoint的使用方式和通知切點表達式
這篇文章主要介紹了SpringBoot?AOP中JoinPoint的使用方式和通知切點表達式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05

