preface

In actual project development, many business scenarios need to use asynchrony to complete, such as message notification, logging, and other very common can be implemented asynchronously to improve efficiency, so how to use asynchrony in the Spring framework

Using the step

There are two common types of asynchronous operations, MQ for message queues, and ThreadPoolExecutor for thread pools

ThreadPoolTaskExecutor, a thread pool wrapped around ThreadPoolExecutor provided in Spring4, directly enables @async with an annotation that makes it easy to perform asynchronous operations with Spring

Configure the thread pool class parameter configuration

Custom constant classes

public class ConstantFiledUtil {
    public static final String AUTHORIZATION_TOKEN = "authorizationToken";
    /** * kmall thread pool name */
    public static final String KMALL_THREAD_POOL = "KmallThreadPool";

    /** * kmall Thread name prefix */
    public static final String KMALL_THREAD_NAME_PREFIX = "kmall-thread-";
}

Copy the code

Configuring a thread pool

@Configuration(proxyBeanMethods = false)
@EnableAsync // Open annotations
public class KmallConfig {
  
  @Bean(ConstantFiledUtil.KMALL_THREAD_POOL)
    public ThreadPoolTaskExecutor FebsShiroThreadPoolTaskExecutor(a) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         // Set the number of core threads
        executor.setCorePoolSize(5);
        // Set the maximum number of threads
        executor.setMaxPoolSize(20);
        // Configure the queue size
        executor.setQueueCapacity(200);
        // The thread pool maintains the idle time allowed by threads
        executor.setKeepAliveSeconds(30);
        // Configure the thread name prefix in the thread pool
        executor.setThreadNamePrefix(ConstantFiledUtil.KMALL_THREAD_NAME_PREFIX);
        // Set the thread pool down to wait for all tasks to complete before continuing to destroy other beans
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // Set the wait time of tasks in the thread pool, and force the task to be destroyed if it has not been destroyed by this time to ensure that the application is eventually shut down rather than blocked
        executor.setAwaitTerminationSeconds(60);
          Rejection -policy: how to deal with a new task when the pool reaches Max size
        // CALLER_RUNS: The task is not executed in a new thread, but by the caller's thread
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // Perform initialization
        executor.initialize();
        returnexecutor; }}Copy the code

Note that asynchrony must be enabled by @enableAsync otherwise it will not work

Custom thread tasks

public interface ILogService extends IService<Log> {

    /** * page search query log information *@param logParams
     * @return* /
    IPage getSearchLogByPage(SearchLogParams logParams);

    /** * Save log **@param logSubject
     */
    @Async
    void saveLog(LogSubject logSubject);
}
Copy the code

You annotate an interface or a method that needs to be executed asynchronously with @async and that method is called asynchronously in the main program and executed asynchronously in a single thread

This annotation indicates that the thread pool entered by the saveLog method was created by the KmallThreadPool method.

We can also specify a separate method name @async (“saveLogs”)

This allows individual threads to respond quickly to each request while logging, leaving time-consuming operations to threads in the thread pool to perform asynchronously

conclusion

Methods marked with the @async annotation in Spring are called asynchronous methods. Using @async in a Spring Boot application is simple:

  1. Call asynchronous method class or start class annotated @enableAsync
  2. Add @async to methods that need to be called asynchronously
  3. The class object of the @Async annotation method used should bea Spring container-managed bean object;

Note that calling asynchronous methods from the same class does not take effect: method calls from the default class are not intercepted by AOP, i.e. the caller and the called are in the same class and cannot generate facets. The object is not managed by the Spring container. That is, the @async method does not take effect

Solutions:

If you want calls between methods in the same class to be intercepted, you need to use an instance object in the Spring container instead of the default this, because calls through bean instances will be intercepted by Spring’s AOP. AsyncService asyncService = context.getBean(AsyncService.class); Note: This method can only intercept protected, default, public methods, but not private methods. This is a mechanism of Spring AOP.

The principle of plane analysis

Asynchronous methods can only have two return types:

  1. When the return type is void, the exception will not be thrown to the calling method invocation process level, can be captured by note AsyncUncaughtExceptionHandler such anomalies

  2. When the return type is Future, exceptions generated during the method call are thrown at the caller level

Note SimpleAsyncTaskExecutor is used by default if the thread pool for asynchronous methods is not customized. SimpleAsyncTaskExecutor: Not a real thread pool. This class does not reuse threads and creates a new thread each time it is called. Serious performance problems can occur when concurrency is large.

Spring’s asynchronous thread pool interface, TaskExecutor

See the source code

@FunctionalInterface
public interface TaskExecutor extends Executor {
    void execute(Runnable var1);
}
Copy the code

Its real predecessors are as follows:

  1. SimpleAsyncTaskExecutor: Not a real thread pool. This class does not reuse threads and creates a new thread each time it is called.

  2. SyncTaskExecutor: This class does not implement an asynchronous call, just a synchronous operation. Only applicable where multithreading is not required

  3. ConcurrentTaskExecutor: Executor adaptation class. This class is not recommended. Consider using this class only if ThreadPoolTaskExecutor does not meet the requirements

  4. SimpleThreadPoolTaskExecutor: is Quartz SimpleThreadPool class. This class is required only if thread pools are used by both Quartz and non-Quartz

  5. ThreadPoolTaskExecutor: Most commonly used, recommended. The essence of which is the Java. Util. Concurrent. ThreadPoolExecutor packaging,

— — — — — — — —

This article refer to

  1. Spring Boot(5) @async Async thread pool
  2. Segmentfault.com/a/119000004…