1. Start an asynchronous task
- In Java applications, interaction processing is implemented through synchronization in the vast majority of cases. When dealing with third-party systems, synchronization is easy to cause slow response
- After Spring 3.x, ** @async ** has been built in to solve this problem perfectly. @async annotates asynchronous execution
- Asynchronous execution either returns null directly or the method does not need to return a value
- Therefore, it is important to note that the return value of the asynchronous method should be able to receive null. It is recommended that there be no return value, because the return value is also null
- Two important notes
- EnableAysnc: Enable asynchronous mode on the startup class
- Aysnc: Methods that require asynchronous processing
- @aysnc Asynchronous method
- Note that the annotation cannot be called from the caller, otherwise the annotation is invalid
- Create an asynchronous execution method
import com.codecoord.util.PrintUtil;
import java.time.LocalDateTime;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncHandler {
@Async
public Long handler(long batch) {
PrintUtil.print("Task The task starts.... Lot No. :" + batch);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
PrintUtil.print("Task Execution is complete.... Lot No. :" + batch + ", completion time:" + LocalDateTime.now());
returnbatch; }}Copy the code
- Create an asynchronous execution controller
import com.codecoord.springboot.practice.async.handler.AsyncHandler;
import java.time.LocalDateTime;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AsyncController {
@Resource
private AsyncHandler asyncHandler;
@RequestMapping("/async")
public Object async(a) {
long batch = System.currentTimeMillis();
return batch + ":" + asyncHandler.handler(batch) + ", completion time:"+ LocalDateTime.now(); }}Copy the code
- The startup class enables the asynchronous function
import com.codecoord.InitialBootApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@InitialBootApplication
@EnableAsync
public class SpringbootAsyncApplication {
public static void main(String[] args) { SpringApplication.run(SpringbootAsyncApplication.class, args); }}Copy the code
- Access the interface, you can see the following processing
Interface return time
1619428692595 : null, completion time:2021-04-26T17:18:12.603
Copy the code
Method Processing time
task-1- Task The task starts.... Batch no. :1619428692595
task-1- Task The task is executed..... Batch no. :1619428692595, completion time:2021-04-26T17:18:15.614
Copy the code
- The interface returns false for the asynchronous method and does not wait for the return value. Method processing time and interface return are independent, that is, the request is received upon return; Method is executed without using the main thread, indicating that thread push is enabled separately
Configure asynchronous thread pools
- @aysnc uses the default thread processing by default. If you need to customize, you need to customize the configuration
- Create a thread configuration class for receiving configuration file configuration parameters
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "async.task.pool")
public class AsyncTaskPoolProperties {
/** * Core thread pool */
private int corePoolSize = 5;
/** * Maximum thread pool */
private int maxPoolSize = 50;
/** * Thread idle */
private int keepAliveSeconds = 60;
/** * Queue length */
private int queueCapacity = 10000;
/** * Thread name prefix */
private String threadNamePrefix = "TX-AsyncTask-";
public int getCorePoolSize(a) {
return corePoolSize;
}
public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
}
public int getMaxPoolSize(a) {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getKeepAliveSeconds(a) {
return keepAliveSeconds;
}
public void setKeepAliveSeconds(int keepAliveSeconds) {
this.keepAliveSeconds = keepAliveSeconds;
}
public int getQueueCapacity(a) {
return queueCapacity;
}
public void setQueueCapacity(int queueCapacity) {
this.queueCapacity = queueCapacity;
}
public String getThreadNamePrefix(a) {
return threadNamePrefix;
}
public void setThreadNamePrefix(String threadNamePrefix) {
this.threadNamePrefix = threadNamePrefix; }}Copy the code
- Implement the AsyncConfigurer interface, which will be provided as the default thread. You can also inherit AsyncConfigurerSupport
- GetAsyncExecutor: Configure the thread executor
- GetAsyncUncaughtExceptionHandler: exception handling methods
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import javax.annotation.Resource;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/** * Thread pool configuration */
@Configuration
public class AsyncTaskPoolConfig implements AsyncConfigurer {
@Resource
private AsyncTaskPoolProperties asyncTaskPoolProperties;
@Override
public Executor getAsyncExecutor(a) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(asyncTaskPoolProperties.getCorePoolSize());
executor.setMaxPoolSize(asyncTaskPoolProperties.getMaxPoolSize());
executor.setKeepAliveSeconds(asyncTaskPoolProperties.getKeepAliveSeconds());
executor.setQueueCapacity(asyncTaskPoolProperties.getQueueCapacity());
executor.setThreadNamePrefix(asyncTaskPoolProperties.getThreadNamePrefix());
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setAllowCoreThreadTimeOut(true);
// Thread pool initialization
executor.initialize();
return executor;
}
/** * Exception handling */
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(a) {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
System.out.println("throwable = " + throwable + ", method = " + method + ", objects = "+ Arrays .deepToString(objects)); }}; }}Copy the code
- You can perform the configuration in a configuration file or you can use the default
async:
task:
pool:
corePoolSize: 10
maxPoolSize: 1000
Copy the code
- Restart the project, then access, and you can see that the thread name will change to the name of the definition
19:22:21.214 - TX-AsyncTask-1- Task The task starts.... Batch no. :1619436141201
19:22:21.752 - TX-AsyncTask-2- Task The task starts.... Batch no. :1619436141752
19:22:22.288 - TX-AsyncTask-3- Task The task starts.... Batch no. :1619436142288
19:22:22.691 - TX-AsyncTask-4- Task The task starts.... Batch no. :1619436142691
19:22:23.101 - TX-AsyncTask-5- Task The task starts.... Batch no. :1619436143101
19:22:24.219 - TX-AsyncTask-1- Task The task is executed..... Batch no. :1619436141201, completion time:2021-04-26T19:22:24.219
19:22:24.759 - TX-AsyncTask-2- Task The task is executed..... Batch no. :1619436141752, completion time:2021-04-26T19:22:24.759
19:22:25.300 - TX-AsyncTask-3- Task The task is executed..... Batch no. :1619436142288, completion time:2021-04-26T19:22:25.300
19:22:25.705 - TX-AsyncTask-4- Task The task is executed..... Batch no. :1619436142691, completion time:2021-04-26T19:22:25.705
19:22:26.111 - TX-AsyncTask-5- Task The task is executed..... Batch no. :1619436143101, completion time:2021-04-26T19:22:26.111
Copy the code