多線程一直是工做或面試過程當中的高頻知識點,今天給你們分享一下使用 ThreadPoolTaskExecutor 來自定義線程池和實現異步調用多線程。面試
本文采用 Executors 的工廠方法進行配置。spring
在項目的 resources 目錄下建立 executor.properties 文件,並添加以下配置:多線程
# 異步線程配置
# 核心線程數
async.executor.thread.core_pool_size=5
# 最大線程數
async.executor.thread.max_pool_size=8
# 任務隊列大小
async.executor.thread.queue_capacity=2
# 線程池中線程的名稱前綴
async.executor.thread.name.prefix=async-service-
# 緩衝隊列中線程的空閒時間
async.executor.thread.keep_alive_seconds=100複製代碼
@Configuration
// @PropertySource是找的target目錄下classes目錄下的文件,resources目錄下的文件編譯後會生成在classes目錄
@PropertySource(value = {"classpath:executor.properties"}, ignoreResourceNotFound=false, encoding="UTF-8")
@Slf4j
public class ExecutorConfig {
@Value("${async.executor.thread.core_pool_size}")
private int corePoolSize;
@Value("${async.executor.thread.max_pool_size}")
private int maxPoolSize;
@Value("${async.executor.thread.queue_capacity}")
private int queueCapacity;
@Value("${async.executor.thread.name.prefix}")
private String namePrefix;
@Value("${async.executor.thread.keep_alive_seconds}")
private int keepAliveSeconds;
@Bean(name = "asyncTaskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
log.info("啓動");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心線程數
executor.setCorePoolSize(corePoolSize);
// 最大線程數
executor.setMaxPoolSize(maxPoolSize);
// 任務隊列大小
executor.setQueueCapacity(queueCapacity);
// 線程前綴名
executor.setThreadNamePrefix(namePrefix);
// 線程的空閒時間
executor.setKeepAliveSeconds(keepAliveSeconds);
// 拒絕策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 線程初始化
executor.initialize();
return executor;
}
}複製代碼
一般 ThreadPoolTaskExecutor 是和 @Async 一塊兒使用。在一個方法上添加 @Async 註解,代表是異步調用方法函數。@Async 後面加上線程池的方法名或 bean 名稱,代表異步線程會加載線程池的配置。app
@Component
@Slf4j
public class ThreadTest {
/**
* 每10秒循環一次,一個線程共循環10次。
*/
@Async("asyncTaskExecutor")
public void ceshi3() {
for (int i = 0; i <= 10; i++) {
log.info("ceshi3: " + i);
try {
Thread.sleep(2000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}複製代碼
備註:必定要在啓動類上添加 @EnableAsync 註解,這樣 @Async 註解纔會生效。異步
// 在啓動類上添加 @EnableScheduling 註解
@SpringBootApplication
@EnableScheduling
public class SpringBootStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootStudyApplication.class, args);
}
}複製代碼
// @Component 註解將定時任務類歸入 spring bean 管理。
@Component
public class listennerTest3 {
@Autowired
private ThreadTest t;
// 每1分鐘執行一次ceshi3()方法
@Scheduled(cron = "0 0/1 * * * ?")
public void run() {
t.ceshi3();
}
}複製代碼
ceshi3() 方法調用線程池配置,且異步執行。async
@Component
@Slf4j
public class ThreadTest {
/**
* 每10秒循環一次,一個線程共循環10次。
*/
@Async("asyncTaskExecutor")
public void ceshi3() {
for (int i = 0; i <= 10; i++) {
log.info("ceshi3: " + i);
try {
Thread.sleep(2000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}複製代碼
經過繼承 CommandLineRunner 類實現。ide
@Component
public class ListennerTest implements CommandLineRunner {
@Autowired
private ThreadTest t;
@Override
public void run(String... args) {
for (int i = 1; i <= 10; i++) {
t.ceshi();
}
}
}複製代碼
@Component
@Slf4j
public class ThreadTest {
@Async("asyncTaskExecutor")
public void ceshi() {
log.info("ceshi");
}
} 複製代碼
還能夠經過接口的形式來異步調用多線程:函數
@RestController
@RequestMapping("thread")
public class ListennerTest2 {
@Autowired
private ThreadTest t;
@GetMapping("ceshi2")
public void run() {
for (int i = 1; i < 10; i++) {
t.ceshi2();
}
}
}複製代碼
@Component
@Slf4j
public class ThreadTest {
@Async("asyncTaskExecutor")
public void ceshi2() {
for (int i = 0; i <= 3; i++) {
log.info("ceshi2");
}
}
} 複製代碼
@RunWith(SpringRunner.class)
@SpringBootTest
public class ThreadRunTest {
@Autowired
private ThreadTest t;
@Test
public void thread1() {
for (int i = 1; i <= 10; i++) {
t.ceshi4();
}
}
}複製代碼
@Component
@Slf4j
public class ThreadTest {
@Async("asyncTaskExecutor")
public void ceshi4() {
log.info("ceshi4");
}
}複製代碼
以上主要介紹了 ThreadPoolTaskExecutor 線程池的配置、使用、相關注解的意義及做用,也簡單介紹了使用 @Async 來異步調用線程,最後又列舉了多線程的使用場景,並配上了代碼示例。但願你們喜歡。工具