How to use Spring annotations @Async asynchronous calls in the project

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 , Task1 execution time 5s, task2 execution time 10s, the two methods in adding @Async

@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);
        }
    }
}

Guess you like

Origin www.cnblogs.com/zeekik/p/11735888.html