特别注意:通常调用方法写在contorller类中,而异步执行业务逻辑放在service类中。
1.controller方法本身就在servlet容器的线程池中同步执行。
2.若controller方法被标记为异步执行,则这个方法会被提交到非servlet容器线程池。
3.若controller方法为同步执行,而被调用方法又需要异步执行,则被调用方法必须放在另一个类中(如service类),异步方法才会被提交到非servlet容器线程池,若不另写一个类,被调用方法仍然在servlet容器线程池中与controller方法一起同步执行。
如果用户未声明异步线程池,spring将开启一个默认线程池来处理异步调用。
@EnableAsync
@Configuration
public class AsyncConfig {
}
/**
* @author: Yang
* @date: 2020/4/6 15:09
* @description:
*/
@Slf4j
@RestController
@RequestMapping("/async")
public class AsyncController {
@Resource
private AsyncService asyncService;
/**
* 无调用关系,无返回值的异步方法
*/
@Async
@GetMapping("/sameClass")
public void sameClass() {
log.error(Thread.currentThread().getName());
}
/**
* 有调用关系,无返回值的异步调用
*/
@GetMapping("/noResult")
public void noResult() {
this.asyncService.no();
}
/**
* 有调用关系,有返回值的异步调用
*
* @return
*/
@GetMapping("/haveResult")
public Long haveResult() {
Long kk = null;
Future<Long> have = this.asyncService.have();
if (have.isDone()) {
try {
kk = have.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
Thread.interrupted();
}
}
return kk;
}
}
@Slf4j
@Component
class AsyncService {
@Async
protected void no() {
log.error(Thread.currentThread().getName());
}
@Async
protected Future<Long> have() {
log.error(Thread.currentThread().getName());
log.error("---------{}", Thread.currentThread().getId());
return new AsyncResult<>(Thread.currentThread().getId());
}
}
http://localhost:8081/async/sameClass //控制台打印出线程name【task-1、task-2、task-3】
http://localhost:8081/async/noResult //控制台打印出线程name【task-1、task-2、task-3】
http://localhost:8081/async/haveResult //能够得到池中线程id【45,12,44】
注:servlet容器线程池的线程名类似【http-nio-8081-exec-1】
/**
* @author: Yang
* @date: 2020/4/6 14:04
* @description:
*/
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {
private static final int MAX_SIZE = 16;
private static final int QUEUE_SIZE = 16;
private static final int KEEP_ALIVE_SECOND = 600;
private static final int AWAIT_TERMINAL_SECOND = 60;
private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors() * 2;
@Bean
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setMaxPoolSize(MAX_SIZE);
pool.setCorePoolSize(CORE_SIZE);
pool.setQueueCapacity(QUEUE_SIZE);
pool.setKeepAliveSeconds(KEEP_ALIVE_SECOND);
pool.setAllowCoreThreadTimeOut(false);
/*
*线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,
*表示当线程池没有处理能力的时候,该策略会直接在execute方法的调用线程中运行这个任务;
*如果执行程序已关闭,则会丢弃该任务
*/
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
pool.setThreadNamePrefix("async-");
// 该方法用来设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。
pool.setWaitForTasksToCompleteOnShutdown(true);
pool.setAwaitTerminationSeconds(AWAIT_TERMINAL_SECOND);
//初始化线程池
pool.initialize();
return pool;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
http://localhost:8081/async/sameClass //控制台打印出线程name【async----1、async----2、async----3】
http://localhost:8081/async/noResult //控制台打印出线程name【async----1、async----2、async----3】
http://localhost:8081/async/haveResult //能够得到池中线程id【45,12,44】
@Override
@Bean("myAsyncPool")
public Executor getAsyncExecutor() {
//自定义线程池声明,略
}
@Async("myAsyncPool")
protected void no() {
//异步执行方法声明,略
}
原文:https://www.cnblogs.com/JaxYoun/p/12643884.html