This paper describes how to use the Spring framework provides an asynchronous call notes @Async, asynchronous thread pool configuration, exception trap handler.
Open @Async annotation support
Before using @Async annotations, call @EnableAsync comment when you must start the project. For example, by defining a JavaConfig file:
@Configuration
@EnableAsync
public class AsyncConfig {
}
Asynchronous call
@Async use asynchronous execution of tasks no return value
Defining a task class AsyncTask, comprising a method of performing time-consuming tasks of two task1 (), task2 (), was added in two ways @Async
@Service
@Slf4j
public class AsyncTask {
@Async
public void task1() {
log.info("task1 start");
}
@Async
public void task2() {
log.info("task2 start");
}
}
Define the test class, serial calls AsyncTask.task1 () and AsyncTask.task2 ()
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class AsyncTaskTest {
@Autowired
private AsyncTask asyncTask;
@Test
public void taskTest() {
log.info("taskTest start");
asyncTask.task1();
asyncTask.task2();
log.info("taskTest end");
}
}
, Task1 and task2 performed separately from the operating results seen in two different threads:
INFO [15:18:29.182][main][com.breezek.demo.common.AsyncTaskTest][25]:taskTest start
INFO [15:18:29.188][main][com.breezek.demo.common.AsyncTaskTest][29]:taskTest end
INFO [15:18:29.192][task-1][com.breezek.demo.common.AsyncTask][29]:task2 start
INFO [15:18:29.192][task-2][com.breezek.demo.common.AsyncTask][24]:task1 start
Asynchronous callbacks
@Async use asynchronous execution have value-returning task, and get task execution results.
AsyncTask defined class, create two asynchronous method return value, the return value of type Future
@Service
@Slf4j
public class AsyncTask {
@Async
public Future<String> task1() throws InterruptedException {
log.info("task1 start");
Thread.sleep(5000L);
log.info("task1 end");
return new AsyncResult<>("task1 result");
}
@Async
public Future<Integer> task2() throws InterruptedException {
Integer abc = 1;
log.info("task2 start");
Thread.sleep(10000L);
log.info("task2 end");
return new AsyncResult<>(abc);
}
}
Define the test class, are calling task1, task2, and wait for the finished task1 and task2
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class AsyncTaskTest {
@Autowired
private AsyncTask asyncTask;
@Test
public void taskTest() throws InterruptedException {
log.info("taskTest start");
Future<String> task1Future = asyncTask.task1();
Future<Integer> task2Future = asyncTask.task2();
// do something
for (int i = 0; i < 1000; i++) {
}
while (!task1Future.isDone() || !task2Future.isDone()) {
}
log.info("taskTest end");
}
}
operation result:
INFO [17:54:24.554][main][com.breezek.demo.common.AsyncTaskTest][28]:taskTest start
INFO [17:54:24.566][task-1][com.breezek.demo.common.AsyncTask][27]:task1 start
INFO [17:54:24.566][task-2][com.breezek.demo.common.AsyncTask][36]:task2 start
INFO [17:54:29.569][task-1][com.breezek.demo.common.AsyncTask][29]:task1 end
INFO [17:54:34.570][task-2][com.breezek.demo.common.AsyncTask][38]:task2 end
INFO [17:54:34.570][main][com.breezek.demo.common.AsyncTaskTest][34]:taskTest end
Can be seen, main thread waits two sub-thread is finished before continuing to run down
When using @Async comment, you need to pay attention to the following points, otherwise the asynchronous call does not take effect:
- The method can not be defined as static induction type
- And a method of asynchronous method invocation can not be defined in the same class
AsyncConfigurer配置
Here's how the code is configured to use the thread pool asynchronous call, void return value exception trap handlers
AsyncConfigurer the interface provided by Spring, we realize that the definition of JavaConfig:
@Configuration
@EnableAsync
@Slf4j
public class AsyncConfig implements AsyncConfigurer {
/**
* 配置线程池,减少在调用每个异步方法时创建和销毁线程所需的时间
*/
@Override
public Executor getAsyncExecutor() {
// 初始化Spring框架提供的线程池
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数
executor.setCorePoolSize(10);
// 最大线程数
executor.setMaxPoolSize(20);
// 任务等待队列大小
executor.setQueueCapacity(10);
// 任务拒绝策略,如果线程池拒绝接受任务,使用调用线程执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 定义线程名称前缀
executor.setThreadNamePrefix("async-executor-");
// 调用线程池初始化方法,如果在getAsyncExecutor()加上了@Bean注解,这个方法可以不调用,因为ThreadPoolTaskExecutor实现了InitializingBean接口,Spring在初始化Bean时会调用InitializingBean.afterPropertiesSet()
executor.initialize();
return executor;
}
/**
* void返回值异步方法异常捕获处理
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
/**
* 异常捕获处理类
*/
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
log.error(String.format("Async method: %s has uncaught exception, params: %s.", method, JSON.toJSONString(params)), ex);
}
}
}