-
配置问题: 首先使用corePoolSize中的线程,corePoolSize满了之后对新的线程排入queueCapacity队列,queueCapacity队列达到了设置的数量后,再根据maxPoolSize的配置数量,继续创建线程(当maxPoolSize > corePoolSize)或者根据策略处理掉溢出任务等(见tt12()及tt13())
-
异步不生效原因之一: 当主类/service类/ExecutorConfig类添加@EnableAsync注解,异步才生效,不然任务还是同步阻塞执行(见tt02())
-
关于Future返回值问题: 异步方法只能设置 void/Future 两种返回值,当返回值为Future,调用main线程会阻塞直到异步方法返回AsyncResult(见tt11())
测试过程需要的类(只有两个+单元测试)
一:AysncService
@Async
@Service
//@EnableAsync
public class AysncService {
public Future<Integer> aysncTest1(){
System.out.println(1);
try {
TimeUnit.MINUTES.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 醒了");
return new AsyncResult<>(1);
}
public Future<Integer> aysncTest2(){
System.out.println(2);
try {
TimeUnit.MINUTES.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 醒了");
return new AsyncResult<>(2);
}
public Future<Integer> aysncTest3(){
System.out.println(3);
try {
TimeUnit.MINUTES.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 醒了");
return new AsyncResult<>(3);
}
public Future<Integer> aysncTest4(){
System.out.println(4);
try {
TimeUnit.MINUTES.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 醒了");
return new AsyncResult<>(4);
}
public Future<Integer> aysncTest5(){
System.out.println(5);
try {
TimeUnit.MINUTES.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 醒了");
return new AsyncResult<>(5);
}
//---------------------
public void aysncTest11(){
System.out.println("1异步开始");
try {
TimeUnit.MILLISECONDS.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 1醒了");
}
public void aysncTest12(){
System.out.println("2异步开始");
try {
TimeUnit.MILLISECONDS.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 2醒了");
}
public void aysncTest13(){
System.out.println("3异步开始");
try {
TimeUnit.MILLISECONDS.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 3醒了");
}
public void aysncTest14(){
System.out.println("4异步开始");
try {
TimeUnit.MILLISECONDS.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 4醒了");
}
public void aysncTest15(){
System.out.println("5异步开始");
try {
TimeUnit.MILLISECONDS.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 5醒了");
}
}
二:ExecutorConfig
@Configuration
@EnableAsync
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
//总结
//① 配置问题: 首先使用corePoolSize中的线程,corePoolSize满了之后之后对新的线程排入queueCapacity队列,queueCapacity队列达到了设置的数量后,再根据maxPoolSize的设置数据,继续创建线程(当maxPoolSize > corePoolSize)或者根据策略处理多余任务等(见tt12()及tt13())
//② @EnableAsync注解问题: 当主类/service类/ExecutorConfig类添加@EnableAsync注解,异步才生效,不然任务还是同步阻塞执行(见tt02())
//③ 关于Future<Integer>返回值问题: 异步方法只能设置 void/Future<T> 两种返回值,当返回值为Future<T>,调用main线程会阻塞直到异步方法返回AsyncResult(见tt11())
private int corePoolSize= 2;//核心线程池
private int queueCapacity = 1;//当任务超过核心线程池数,允许排在队列中的任务数
private int maxPoolSize = 3;//当排在队列中的任务也满了,允许创建的最大线程总数
private String namePrefix = "thread-77";//线程名字
@Bean
public Executor asyncServiceExecutor() {
logger.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(corePoolSize);
//配置最大线程数
executor.setMaxPoolSize(maxPoolSize);
//配置队列大小
executor.setQueueCapacity(queueCapacity);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix(namePrefix);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
// AbortPolicy:抛出RejectedExecutionException
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
三:单元测试方法整体代码
@Autowired
private AysncService aysncService;
@Test
public void tt11(){
try {
//接收Future<Integer> future 返回值会使异步失效!!! 当前main会阻塞
Future<Integer> future1 = aysncService.aysncTest1();
System.out.println(future1.get());
Future<Integer> future2 = aysncService.aysncTest2();
System.out.println(future2.get());
Future<Integer> future3 = aysncService.aysncTest3();
System.out.println(future3.get());
Future<Integer> future4 = aysncService.aysncTest4();
System.out.println(future4.get());
Future<Integer> future5 = aysncService.aysncTest5();
System.out.println(future5.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Test
public void tt02(){
//本方法验证当主类/service类/ExecutorConfig类不添加@EnableAsync注解时,异步不生效问题
//结果:
//当主类/service类/ExecutorConfig类不添加@EnableAsync注解,1 2 3 4 按顺序输出
//当主类/service类/ExecutorConfig类添加@EnableAsync注解,1 2 3 4 异步同时输出
aysncService.aysncTest11();
System.out.println("1异步ok");
aysncService.aysncTest12();
System.out.println("2异步ok");
aysncService.aysncTest13();
System.out.println("3异步ok");
aysncService.aysncTest14();
System.out.println("4异步ok");
try {
Thread.currentThread().join(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void tt12(){
//本方法ExectorConfig需配置为:
// private int corePoolSize= 2;//核心线程池
// private int queueCapacity = 1;//当任务超过核心线程池数,允许排在队列中的任务数
// private int maxPoolSize = 3;//当排在队列中的任务也满了,允许创建的最大线程总数
//本方法验证:CorePoolSize(2)执行两个任务,queueCapacity(1)队列中排一个任务,超出队列再由maxPoolSize(3-2)执行一个任务
//也就是异步执行3个任务+排队1个任务
aysncService.aysncTest11();
System.out.println("1异步ok");
aysncService.aysncTest12();
System.out.println("2异步ok");
aysncService.aysncTest13();
System.out.println("3异步ok");
aysncService.aysncTest14();
System.out.println("4异步ok");
try {
Thread.currentThread().join(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void tt13(){
//本方法验证:CorePoolSize(3)执行两个任务,queueCapacity(0)队列中无排队任务,超出队列再由maxPoolSize(4-3)执行一个任务
//也就是异步执行4个任务+排队0个任务+超出maxPoolSize 1个任务抛出RejectedExecutionException
//本方法ExectorConfig需配置为:
// private int corePoolSize= 3;//核心线程池
// private int queueCapacity = 0;//当任务超过核心线程池数,允许排在队列中的任务数
// private int maxPoolSize = 4;//当排在队列中的任务也满了,允许创建的最大线程总数
try {
aysncService.aysncTest11();
System.out.println("1异步ok");
aysncService.aysncTest12();
System.out.println("2异步ok");
aysncService.aysncTest13();
System.out.println("3异步ok");
aysncService.aysncTest14();
System.out.println("4异步ok");
aysncService.aysncTest15();
System.out.println("5异步ok");
} catch (Exception e) {
e.printStackTrace();
}
//以上有一个任务会抛出RejectedExecutionException
try {
Thread.currentThread().join(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}