目錄
- 前言
- 一、異步調用實作
- 二、@Async整合線程池
前言
- @Async實際就是多線程封裝的
- 異步線程執行方法有可能會非常消耗cpu的資源,是以大的項目建議使用Mq異步實作
一、異步調用實作
- 1.啟動類需要添加注解
@EnableAsync
@SpringBootApplication
@EnableAsync
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
- 2.需要執行異步的方法上加上注解
@Async
- 注意失效問題:如果異步注解寫目前自己類,有可能aop會失效,無法攔截注解,最終導緻異步注解失效,需要經過代理類調用接口;是以需要将異步的代碼單獨抽取成一個類調用接口
@RestController
@Slf4j
public class MemberService {
@Autowired
private MemberServiceAsync memberServiceAsync;
@RequestMapping("/addMember")
public String addMember() {
// 1.資料庫插入資料
log.info(">01<");
memberServiceAsync.sms();
log.info(">04<");
return "使用者注冊成功";
}
}
@Component
@Slf4j
public class MemberServiceAsync {
@Async
public String sms() {
log.info(">02<");
try {
log.info(">正在發送短信..<");
Thread.sleep(3000);
} catch (Exception e) {
}
log.info(">03<");
return "短信發送完成!";
}
}

二、@Async整合線程池
- 1.在第一點的例子中雖然我們實作了異步多線程,但是還有缺點
- 每次都重新開啟一個線程,這樣非常消耗資源影響效率
- 我們需要整合線程池來優化,提高程式的性能
八、SpringBoot整合多線程異步前言一、異步調用實作二、@Async整合線程池
- 2.項目結構
- 3.ThreadPoolConfig
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 java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class ThreadPoolConfig {
/**
* 每秒需要多少個線程處理?
* tasks/(1/taskcost)
*/
private int corePoolSize = 3;
/**
* 線程池維護線程的最大數量
* (max(tasks)- queueCapacity)/(1/taskcost)
*/
private int maxPoolSize = 3;
/**
* 緩存隊列
* (coreSizePool/taskcost)*responsetime
*/
private int queueCapacity = 10;
/**
* 允許的空閑時間
* 預設為60
*/
private int keepAlive = 100;
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 設定核心線程數
executor.setCorePoolSize(corePoolSize);
// 設定最大線程數
executor.setMaxPoolSize(maxPoolSize);
// 設定隊列容量
executor.setQueueCapacity(queueCapacity);
// 設定允許的空閑時間(秒)
//executor.setKeepAliveSeconds(keepAlive);
// 設定預設線程名稱
executor.setThreadNamePrefix("thread-");
// 設定拒絕政策rejection-policy:當pool已經達到max size的時候,如何處理新任務
// CALLER_RUNS:不在新線程中執行任務,而是有調用者所在的線程來執行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任務結束後再關閉線程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
- 4.在@Async()注解中配置屬性"taskExecutor"
@Component
@Slf4j
public class MemberServiceAsync {
@Async("taskExecutor")
public String sms() {
log.info(">02<");
try {
log.info(">正在發送短信..<");
Thread.sleep(3000);
} catch (Exception e) {
}
log.info(">03<");
return "短信發送完成!";
}
/**
* 線程池
*/
}