今天来记录一下通过注解来实现异步操作的功能。
在这里我们需要用到两个注解:
- @EnableAsync:用来开启异步执行的监听
- @Async:用来标注异步方法
通过这两个注解可以很简单的实现异步执行方法 ,也就是开启多线程。
1、在启动类处开启添加@EnableAsync
注解
package com.youyou.sso; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; @EnableScheduling @ServletComponentScan @SpringBootApplication @EnableAsync public class ApiServerApplication { public static void main(String[] args) { SpringApplication.run(ApiServerApplication.class, args); } }
2、在service处添加@Async
注解
package com.youyou.sso.service.impl; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; /** * //TODO 添加类/接口功能描述 * * @date 2021-10-20 */ @Service public class AsyncTestService { // @Async("asyncServiceExecutor") @Async public void test1() throws InterruptedException { System.out.println(1); Thread.sleep(10000); System.out.println(2); } // @Async("asyncServiceExecutor") @Async public void test2() throws InterruptedException { System.out.println(3); Thread.sleep(10000); System.out.println(4); } }
3、测试
package com.youyou.sso.controller; import com.youyou.sso.bean.UserInfo; import com.youyou.sso.service.ISsoService; import com.youyou.sso.service.impl.AsyncTestService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; /** * //TODO 添加类/接口功能描述 * * @date 2021-09-06 */ @Api(value = "异步测试", tags = "testAsync") @RestController("") @RequestMapping("/testAsync") public class AsyncTestController { @Autowired private AsyncTestService asyncTestService; @ApiOperation(value = "|test|") @GetMapping("/test") public void login() throws InterruptedException { asyncTestService.test1(); asyncTestService.test2(); } }
调用此接口时控制台会输出如下:
1 3 4 2
进阶内容
我们可以自己进行线程池的配置
package com.youyou.sso.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; //@Configuration //@EnableAsync public class ExecutorConfig { // @Bean(name = "asyncServiceExecutor") // @Bean public Executor executor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(5); //配置最大线程数 executor.setMaxPoolSize(5); //配置队列大小 executor.setQueueCapacity(99999); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix("async-service-"); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; } // @Bean(name = "asyncServiceExecutor1") public Executor asyncServiceExecutor() { return executor(); } }
在bean注解的name处指定线程池的名字,并且在使用@Async
注解时添加此线程池的名字就可以了
参考: