SpringBoot實踐之---@EnableAsync和@Async 線程池自定義和使用

    自定義線程池的配置類  AsyncConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
/** 
* @Description: 自定義線程池的配置類,並在類上添加@EnableAsync 註解,
 * 然後在需要異步的方法上使用@Async("線程池名稱") 該方法就可以異步執行了
* @Param:  * @param null 
* @return:  
* @Author: wenliang 
* @Date: 2019/11/6 
**/ 
public class AsyncConfig {
	private static final Logger logger = LoggerFactory.getLogger(AsyncConfig.class);
	@Bean("taskExecutor") // bean的名稱,,不寫的裏面值,則默認爲首字母小寫的方法名
	public TaskExecutor taskExecutor() {
		logger.info("start asyncServiceExecutor");
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		int core = Runtime.getRuntime().availableProcessors();
		//配置核心線程數
		executor.setCorePoolSize(core);
		//配置最大線程數
		executor.setMaxPoolSize(core * 2 + 1);
		// 允許線程空閒時間(單位:默認爲秒)
		executor.setKeepAliveSeconds(5);
		//配置隊列大小
		executor.setQueueCapacity(9999);
		//配置線程池中的線程的名稱前綴
		executor.setThreadNamePrefix("async-service-");

		// rejection-policy:當pool已經達到max size的時候,如何處理新任務
		// CALLER_RUNS:不在新線程中執行任務,而是有調用者所在的線程來執行
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.setWaitForTasksToCompleteOnShutdown(true);
		//執行初始化
		executor.initialize();
		return executor;
	}

}

注① @Configuration用於定義配置類,可替換xml配置文件,被註解的類內部包含有一個或多個被@Bean註解的方法,這些方法將會被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext類進行掃描,並用於構建bean定義,初始化Spring容器。

注② @EnableAsync開始對異步任務的支持

接着寫個service類 testAsyncService :
 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
 
@Service
public class testAsyncService {
	Logger log = LoggerFactory.getLogger(testAsyncService.class);
 
	// 發送提醒短信 1
	@Async("taskExecutor")
	public void service1() throws InterruptedException {
		log.info("--------start-service1------------");
		Thread.sleep(5000); // 模擬耗時
	    log.info("--------end-service1------------");
	}
	
	// 發送提醒短信 2
	@Async("taskExecutor")
	public void service2() throws InterruptedException {
		
		log.info("--------start-service2------------");
		Thread.sleep(2000); // 模擬耗時
	    log.info("--------end-service2------------");
 
	}

注① 使用@Async註解來聲明一個或多個異步任務,可以加在方法或者類上,加在類上表示這整個類都是使用這個自定義線程池進行操作

接着我們可以創建control類@Autowired這個service並且調用這其中兩個方法,進行連續調用,會發現運行結果是

     --------start-service1------------

     --------start-service2------------

     --------end-service2------------

     --------end-service1------------

可以說明我們的異步運行成功了

注意點:

一、異步方法使用static修飾
二、異步類沒有使用@Component註解(或其他註解)導致spring無法掃描到異步類
三、類中需要使用@Autowired或@Resource等註解自動注入,不能自己手動new對象
五、如果使用SpringBoot框架必須在啓動類中增加@EnableAsync註解
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章