線程池配置
/**
* 定義線程池
* @return
*/
@Bean("myThreadPool")
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);//配置核心線程數
executor.setMaxPoolSize(20);//配置最大線程數
executor.setKeepAliveSeconds(5);
executor.setQueueCapacity(200);//配置隊列大小
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//拒絕策略
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();//執行初始化
return executor;
}
異步任務
package com.test.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@Service
public class MyServiceImpl {
//volatile保證了靜態變量的可見性(visibility),
public static volatile AtomicInteger i = new AtomicInteger(0);
/**
* 無返回結果
*/
@Async("myThreadPool")
public void test() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("當前第"+ i.incrementAndGet() +"次執行");
}
/**
* 有返回結果
* @return
*/
@Async("myThreadPool")
public Future<String> test2() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult("當前第"+ i.incrementAndGet() +"次執行");
}
}
開啓異步任務
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class MyTestApplication {
public static void main(String[] args) {
SpringApplication.run(MyTestApplication .class, args);
}
}
注意
注意:
關於@Async註解失效需要注意以下幾點:
- 註解的方法必須是public方法。
- 方法一定要從另一個類中調用,也就是從類的外部調用,類的內部調用是無效的。因爲@Transactional和@Async註解的實現都是基於Spring的AOP,而AOP的實現是基於動態代理模式實現的。那麼註解失效的原因就很明顯了,有可能因爲調用方法的是對象本身而不是代理對象,因爲沒有經過Spring容器。
- 異步方法使用註解@Async的返回值只能爲void或者Future。
- 自定義的線程池必須與@Async()不在同一個類中