因为业务需要,出现了异步方法调用异步方法的现象,而且两个异步方法都使用了同一个异步线程池。但是这种会有一定的问题,下边先分析一下:
异步线程A调用了异步线程X。执行A的时候从线程池拿了一个线程,结果执行到X的时候线程池满了,加入了等待队列,但是此时线程池的线程A在等待X的执行结果,没有返回就不会释放,进入了死锁。。
但是如果你配置了超时释放时间,或者等待队列无限大,或者拒绝策略是直接丢弃,其实是不会出现这种情况的,但是合理的异步使用方法是需要做到线程池隔离的,所以我就把原来单一的线程池配置变成了多个线程池配置。
这是单个的配置:
@Configuration
public class AsyncConfig extends AsyncConfigurerSupport {
@Bean("asyncExecutor")
public ThreadPoolTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
threadPool.setCorePoolSize(30);
threadPool.setMaxPoolSize(200);
threadPool.setWaitForTasksToCompleteOnShutdown(true);
threadPool.setAwaitTerminationSeconds(60 * 15);
threadPool.setThreadFactory(
new ThreadFactoryBuilder().setNameFormat("async-thread-pool-%d").build());
return threadPool;
}
@Override
public Executor getAsyncExecutor() {
return asyncExecutor();
}
}
这是多个的配置
@Configuration
@EnableAsync
public class AsyncConfig{
private ThreadPoolTaskExecutor asyncExecutor(String prefix) {
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
threadPool.setCorePoolSize(30);
threadPool.setMaxPoolSize(200);
threadPool.setWaitForTasksToCompleteOnShutdown(true);
threadPool.setAwaitTerminationSeconds(60 * 15);
threadPool.setThreadFactory(
new ThreadFactoryBuilder().setNameFormat("async-thread-pool-"+ prefix +"-%d").build());
return threadPool;
}
@Bean("asyncExecutor")
public AsyncTaskExecutor getFirstAsync(){
return asyncExecutor("first");
}
@Bean("secondExecutor")
public AsyncTaskExecutor getSecondAsync(){
return asyncExecutor("second");
}
}
下边进行具体的测试:
@Service
@Slf4j
public class TestService {
@Async("asyncExecutor")
public Future<String> testF(String first){
String flag = "7777777" + " is: " + first;
System.out.println(flag);
System.out.println(Thread.currentThread().getName());
return new AsyncResult(flag);
}
@Async("secondExecutor")
public Future<String> testS(String first){
String flag = "6666666" + " is: " + first;
System.out.println(flag);
System.out.println(Thread.currentThread().getName());
return new AsyncResult(flag);
}
}
测试代码如下:
@Resource
private TestService testService;
@Test
public void asyncTest(){
Future<String> ff = testService.testF("first");
Future<String> ss = testService.testS("second");
String f = "";
String s = "";
try{
f = ff.get();
s = ss.get();
} catch (Exception e){
System.out.println("e occur.");
}
System.out.println("done");
System.out.println(f);
System.out.println(s);
}
调用结果如下:
可以清楚地看到,两个异步使用了不同的线程池~
问题解决