線程池,從名字上來看,就是一個保存線程的"池子",凡事都有其道理,那線程池的好處在哪裏呢?java
咱們要讓計算機爲咱們幹一些活,其實都是在使用線程,使用方法就是new一個Runnable接口或者新建一個子類,繼承於Thread類,這就會涉及到線程對象的建立與銷燬,這兩個操做無疑是耗費咱們系統處理器資源的,那如何解決這個問題呢? 線程池其實就是爲了解決這個問題而生的。spring
線程池提供了處理系統性能和大用戶量請求之間的矛盾的方法,經過對多個任務重用已經存在的線程對象,下降了對線程對象建立和銷燬的開銷,因爲當客戶請求到了時,線程對象已經存在,能夠提升請求的響應時間從而總體的提升了系統服務的表現。bash
本篇博客就是要總結一下,如何在Spring中使用異步線程池,給你們一個例子,去體會一下異步這個概念app
實習生小王負責後臺管理系統的報表分析,他的工做是負責操做後臺系統,點擊按鈕,生成數據報表,而並不須要查看報表,因爲數據量大, 生成報表須要花費很長時間,而若是生成報表和其餘工做在一個線程,小王就沒法幹其餘工做了,因此須要將生成報表這個任務交給計算機的其餘線程,這即是異步的體現。異步
在Spring中使用異步線程池async
spring中提供了AsyncConfigurer這個配置接口,便於咱們配置本身的異步線程池。ide
我習慣新建一個config包,而後將一些組件的配置類都放到裏面性能
package com.example.wyh.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* @author 陽光大男孩!!!
*/
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
//定義線程池
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
//設置核心線程數
threadPoolTaskExecutor.setCorePoolSize(10);
//設置線程池最大線程數
threadPoolTaskExecutor.setMaxPoolSize(30);
//設置線程隊列最大線程數
threadPoolTaskExecutor.setQueueCapacity(2000);
//初始化線程池
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
複製代碼
在上面代碼中,咱們使用@Configuration告訴spring這是一個配置類,使用註解@EnableAsync讓spring開啓異步可用。 這樣之後若是想把某個方法中的任務異步地放到另一個線程,只須要經過方法上加 @Async註解便可。測試
package com.example.wyh.Service;
/**
* @author 陽光大男孩!!!
*/
public interface AsyncService {
/**
* 測試使用異步線程池來執行工做
*/
public void useAsyncThreadWork();
}
複製代碼
package com.example.wyh.Service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* @author 陽光大男孩!!!
*/
@Service
public class AsyncServiceImp implements AsyncService{
@Override
@Async
public void useAsyncThreadWork() {
System.out.println(Thread.currentThread().getName());
}
}
複製代碼
在接口的具體實現中,咱們打印了當前線程的名稱,藉以來查看是不是在一個心的線程中執行該任務。而且經過@Service註解告訴spring這是一個Service類型的bean,這樣咱們就可讓spring經過其自身容器來管理咱們的對象,這就是IOC特性的一個體現。ui
/**
* @author 陽光大男孩!!!
*/
@RestController
public class AsyncController {
@Autowired
AsyncService asyncService;
@GetMapping("/testAsync")
public String testAsync()
{
System.out.println(Thread.currentThread().getName());
asyncService.useAsyncThreadWork();
return "testAsync方法執行成功...";
}
}
複製代碼
能夠看到,在上述代碼中,咱們使用 @Autowired註解自動裝配了剛纔交給Spring容器管理的Service實現類對象,這是spring 的DI特性體現。
因爲我開的是8090端口,因此我訪問的是8090端口
能夠看到打印了兩個線程的名稱,第一個是在Controller中執行的線程名稱,第二個則是spring經過咱們剛纔的配置,爲咱們從線程池中提取的線程併爲咱們執行相應任務。
本篇博客簡介了在spring中使用線程池異步執行任務的基本方法,爲在項目中使用異步線程池提供了示例。