自定義線程池的配置類 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註解