Spring
是通過任務執行器(TaskExecutor
)來實現多線程和併發編程,使用ThreadPoolTaskExecutor
來創建一個基於線城池的TaskExecutor
。在使用線程池的大多數情況下都是異步非阻塞的。我們配置註解@EnableAsync
可以開啓異步任務。然後在實際執行的方法上配置註解@Async
上聲明是異步任務。
分爲三步:1.配置線程池管理 Executor ;2.配置異步方法;3.執行異步方法
1.配置線程池管理 Executor
新建一個配置類:
@Configuration
@EnableAsync
public class ThreadConfig {
@Bean
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//設置線程池的大小
executor.setCorePoolSize(5);
//設置線程池的最大值
executor.setMaxPoolSize(15);
//設置線程池的最大值
executor.setQueueCapacity(250);
//初始換線程池
executor.initialize();
return executor;
}
}
2.配置異步方法
@Service
public class AsyncTaskService {
@Async("getAsyncExecutor")
public void executeAsyncTask() {
//do something
}
}
3.執行異步方法
像正常調用方法即可
常見問題:
1.java.lang.InterruptedException: sleep interrupted
如果在測試類裏調用異步方法,可能會出現子線程還未執行完,父線程已經關閉。則可以在父線程裏增加Thread.sleep()方法,等一等子線程
2.Only one AsyncAnnotationBeanPostProcessor may exist within the context.
可能是對某個bean配置了多次,可以註釋掉 xml配置裏的 註解
<task:annotation-driven/>
3.Executor [java.util.concurrent.ThreadPoolExecutor@497ed877[Running, pool size = 15, active threads = 15, queued tasks = 20, completed tasks = 0]] did not accept task: org.springframework.aop.interceptor.AsyncExecutionInterceptor$$LambdaXXXX
可能是 “線程池的最大數+隊列數>你的併發數” ,你需要增加你的隊列容量,
executor.setQueueCapacity(20); 將20調大即可