This is the 19th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021

In addition to implementing its own threads, SpringBoot itself provides an annotated way to perform asynchronous tasks. The following is mainly to record the implementation of asynchronous tasks in the Springboot project, as well as the encapsulation monitoring of asynchronous tasks.

1 Enable asynchronous support

To use SpringBoot annotations for asynchronous tasks, you must first enable SpringBoot’s asynchronous task support. By integrating the AsyncConfigurer interface and implementing the getAsyncExcutor() method, as follows:

package com.springboot.demo.asyncTask.conf; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; // @configuration @enableAsync // Enable asynchronous task support public Class SpringTaskExecutor implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(20); taskExecutor.initialize(); return taskExecutor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return null; }}Copy the code

With the above method, you can implement Spring Boot’s asynchronous task support. Then just add the @async annotation to the method that you want to Async, as shown below:

package com.springboot.demo.asyncTask.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; /** * asynchronous task executor */ @Component public class AsyncTaskExecutor {private static Logger LOG = LoggerFactory.getLogger(AsyncTaskExecutor.class); @Async public void executor(AsyncTaskConstructor asyncTaskGenerator, String taskInfo) { LOG.info("AsyncTaskExecutor is executing async task:{}", taskInfo); asyncTaskGenerator.async(); }}Copy the code

2 Monitor the encapsulation of asynchronous tasks

2.1 Encapsulation Roadmap

Provides an asynchronous task manager. The manager can submit, save, and obtain asynchronous task information.

Provides an asynchronous task monitor that monitors the execution of asynchronous tasks, saves execution information in the cache, and records the execution time of tasks.

Provides an asynchronous task constructor for constructing asynchronous methods.

Provides an executor for an asynchronous task that executes an asynchronous method submitted by the manager that is constructed using the constructor.

2.2 Effect Display

2.2.1 Starting an Asynchronous Task

2.2.2 Viewing the Task Status

2.3 Coding Implementation

2.3.1 the conf package

The main task is to configure the Thread pool of Spring Boot and enable spring Boot to support asynchronous support

2.3.1.1 SpringTaskExcutor. Java

package com.emcc.hiacloud.analytics.asynctask.conf; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; // @configuration @enableAsync // Enable asynchronous task support public Class SpringTaskExecutor implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(20); taskExecutor.initialize(); return taskExecutor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return null; }}Copy the code

2.3.2 entity package

The TaskInfo instance class is used to store task information, and the TaskStatusEnmu enumeration class is used to store task status.

2.3.2.1 TaskInfo. Java

package com.emcc.hiacloud.analytics.asynctask.entity; import java.util.Date; /** * public class TaskInfo {private String TaskInfo; private TaskStatusEnum status; private Date startTime; private Date endTime; private String totalTime; public TaskStatusEnum getStatus() { return status; } public void setStatus(TaskStatusEnum status) { this.status = status; } public void setTotalTime(String totalTime) { this.totalTime = totalTime; } public String getTaskId() { return taskId; } public void setTaskId(String taskId) { this.taskId = taskId; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public String getTotalTime() { return totalTime; } public void setTotalTime() { this.totalTime = (this.endTime.getTime() - this.startTime.getTime()) + "ms"; }}Copy the code

2.3.2.2 TaskStatusEnum. Java

package com.emcc.hiacloud.analytics.asynctask.entity; Public enum TaskStatusEnum {STARTED(1, "STARTED "), RUNNING(0," STARTED "), SUCCESS(2, "succeeded "), FAILED(-2, "Task execution FAILED "); private int state; private String stateInfo; TaskStatusEnum(int state, String stateInfo) { this.state = state; this.stateInfo = stateInfo; } public int getState() { return state; } public String getStateInfo() { return stateInfo; }}Copy the code

2.3.3 manager package

Holds the management and monitoring classes for tasks

2.3.3.1 AsyncTaskManager. Java

package com.emcc.hiacloud.analytics.asynctask.manager; import com.emcc.hiacloud.analytics.asynctask.entity.TaskInfo; import com.emcc.hiacloud.analytics.asynctask.entity.TaskStatusEnum; import com.emcc.hiacloud.analytics.asynctask.service.AsyncTaskConstructor; import com.emcc.hiacloud.analytics.asynctask.service.AsyncTaskExecutor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; @Component public class AsyncTaskManager {private Map<String, TaskInfo> taskContainer = new HashMap<>(16); @Autowired AsyncTaskExecutor asyncTaskExecutor; /** * @taskinfo */ public taskInfo initTask() {taskInfo taskInfo = new taskInfo (); taskInfo.setTaskId(getTaskId()); taskInfo.setStatus(TaskStatusEnum.STARTED); taskInfo.setStartTime(new Date()); setTaskInfo(taskInfo); return taskInfo; } /** * public taskInfo submit(asyncTaskConstructor) asyncTaskConstructor) { TaskInfo info = initTask(); String taskId = info.getTaskId(); asyncTaskExecutor.executor(asyncTaskConstructor,taskId); return info; } /** * @param taskInfo */ public void setTaskInfo(taskInfo taskInfo) { taskContainer.put(taskInfo.getTaskId(), taskInfo); } /** * getTaskInfo ** @param taskId taskId * @return */ public TaskInfo getTaskInfo(String taskId) {return taskContainer.get(taskId); } /** * getTaskStatus ** @param taskId taskId * @return */ public TaskStatusEnum getTaskStatus(String taskId) {return getTaskInfo(taskId).getStatus(); } /** * @taskid */ public String getTaskId() {return uid.randomuuid ().toString(); }}Copy the code

2.3.3.2 AsyncTaskMonitor. Java

Asynchronous task monitoring is mainly the use of spring AOP aspect, before and after the execution of asynchronous method to monitor, judge the task state, and record the task information.

package com.emcc.hiacloud.analytics.asynctask.manager; import com.emcc.hiacloud.analytics.asynctask.entity.TaskInfo; import com.emcc.hiacloud.analytics.asynctask.entity.TaskStatusEnum; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Date; / / @component@aspect public class AsyncTaskMonitor {@autoWired AsyncTaskManager; private static Logger LOG = LoggerFactory.getLogger(AsyncTaskMonitor.class); @Around("execution(* com.emcc.hiacloud.analytics.asynctask.service.AsyncTaskExecutor.*(..) )") public void taskHandle(ProceedingJoinPoint PJP) {// Get taskId String taskId = pjp.getargs ()[1].toString(); TaskInfo TaskInfo = manager.gettAskInfo (taskId); LOG.info("AsyncTaskMonitor is monitoring async task:{}", taskId); taskInfo.setStatus(TaskStatusEnum.RUNNING); manager.setTaskInfo(taskInfo); TaskStatusEnum status = null; try { pjp.proceed(); status = TaskStatusEnum.SUCCESS; } catch (Throwable throwable) { status = TaskStatusEnum.FAILED; LOG.error("AsyncTaskMonitor:async task {} is failed.Error info:{}", taskId, throwable.getMessage()); } taskInfo.setEndTime(new Date()); taskInfo.setStatus(status); taskInfo.setTotalTime(); manager.setTaskInfo(taskInfo); }}Copy the code

2.3.4 service package

It mainly houses method constructors and actuators for asynchronous tasks.

2.3.4.1 AsyncTaskConstructor

This interface allows you to build asynchronous methods that you want to implement. Simply new the interface instance and override the async() method.

package com.emcc.hiacloud.analytics.asynctask.service; Public interface AsyncTaskConstructor {public void async(); }Copy the code

2.3.4.2 AsynctAskExecutor. Java Asynchronous task executor

package com.emcc.hiacloud.analytics.asynctask.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; /** * asynchronous task executor */ @Component public class AsyncTaskExecutor {private static Logger LOG = LoggerFactory.getLogger(AsyncTaskExecutor.class); @Async public void executor(AsyncTaskConstructor asyncTaskGenerator, String taskInfo) { LOG.info("AsyncTaskExecutor is executing async task:{}", taskInfo); asyncTaskGenerator.async(); }}Copy the code

3 application

Realize two interfaces, one is to start an asynchronous task, another is to view the status of the task.

To use the asynchronous task we just assembled, just inject AsyncTaskManager into the program.

package com.emcc.hiacloud.analytics.orchestrations.controller; import com.emcc.hiacloud.analytics.asynctask.entity.TaskInfo; import com.emcc.hiacloud.analytics.asynctask.manager.AsyncTaskManager; import com.emcc.hiacloud.analytics.common.rest.RestMessage; import com.emcc.hiacloud.analytics.common.util.RestMessageUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @restController @RequestMapping(value = "/ API /v1/ AsyncTask ") Public Class AsyncTaskController {// Inject AsyncTaskController @autoWired AsyncTaskManager asyncTaskManager; @RequestMapping(value = "/startTask", Method = requestMethod.get) public RestMessage startAsyncTask() {// Call submit in task manager to submit an asynchronous task TaskInfo TaskInfo = asyncTaskManager.submit(() -> { System.out.println("__________"); Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("__________"); }); return RestMessageUtil.objectToRestMessage(taskInfo); } @RequestMapping(value = "/getTaskStatus", method = RequestMethod.GET) public RestMessage getTaskStatus( @RequestParam("taskId") String taskId) { return RestMessageUtil.objectToRestMessage(asyncTaskManager.getTaskInfo(taskId)); }}Copy the code