1、启动类上添加@EnableAsync注解,表示启动异步
2、在具体实现异步的方法上添加@Async注解
- package com.example.demo;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.scheduling.annotation.EnableAsync;
-
- @SpringBootApplication
- @EnableAsync
- public class DemoApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
-
- }
- package com.example.demo;
-
-
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Component;
-
- /**
- * @Description: TODO
- * @author: sl
- * @date: 2024年05月30日 21:55
- */
- @Component
- public class DemoController {
-
- /**
- * Async相当于是方法级别的线程,本身没有自定义线程池更加灵活
- * 相当于是每进来一个请求就开启一个线程,超过核心线程数小于最大线程数放入队列,
- * 队列满了,继续创建线程直至达到最大线程数
- * @throws InterruptedException
- */
- @Async
- public void testSync() throws InterruptedException {
- Thread.sleep(2000);
- System.out.println("异步执行成功");
- }
- }
- package com.example.demo;
-
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
-
- @SpringBootTest
- class DemoApplicationTests {
-
- @Autowired
- private DemoController demoController;
-
- @Test
- void contextLoads() throws InterruptedException {
- demoController.testSync();
- System.out.println("主线程执行");
- Thread.sleep(4000);
- }
-
- }

SpringBoot会默创建了一个线程池,使用这里面的线程来执行异步调用,在项目中使用
Executors 是一个 Java 中的工具类。提供四种线程池创建方式,工厂方法来创建不同类型的线程池。Executors 的创建线程池的方法,创建出来的线程池都实现了ExecutorService 接口,
1.newFiexedThreadPool(int Threads):创建固定数目线程的线程池。
2.newCachedThreadPool():创建一个可缓存的线程池,调用 execute将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
3.newSingleThreadExecutor() 创建一个单线程化的 Executor。
4.newScheduledThreadPool(int corePoolSize) 创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代 Timer 类不建议大家使用Executors这个类来创建线程池呢,阿里开发手册这样定义:
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM
2) CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE, 可能会创建大量的线程,从而导致 OOM
使用常见的三种线程池创建方式,单一、可变、定长都有一定问题,原因是 FixedThreadPool 和 SingleThreadExecutor 底层都是用LinkedBlockingQueue 实现的,这个队列最大长度为 Integer.MAX_VALUE,容易导致 OOM
所以实际生产一般自己通过 ThreadPoolExecutor 的 7 个参数,自定义线程池
springboot创建线程池,Spring提供的对ThreadPoolExecutor封装的线程池ThreadPoolTaskExecutor,直接使用注解启用。
Async相当于是方法级别的线程,本身没有自定义线程池更加灵活
- package com.example.demo.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.task.TaskExecutor;
- import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-
- import java.util.concurrent.ThreadPoolExecutor;
-
- /**
- * @Description: TODO
- * @author: sl
- * @date: 2024年05月30日 22:37
- */
- @Configuration
- public class MyPoolConfig {
- @Bean
- public TaskExecutor taskExecutor(){
- ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- //设置核心线程数
- executor.setCorePoolSize(10);
- //设置最大线程数
- executor.setMaxPoolSize(15);
- //设置队列容量
- executor.setQueueCapacity(20);
- //设置线程活跃时间(秒)
- executor.setKeepAliveSeconds(60);
- //设置默认线程名称
- executor.setThreadNamePrefix("1111-");
- //设置拒绝策略
- executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
- //等待所有任务结束后再关闭线程池
- executor.setWaitForTasksToCompleteOnShutdown(true);
- return executor;
- }
-
- }
- package com.example.demo;
-
-
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Component;
-
- /**
- * @Description: TODO
- * @author: sl
- * @date: 2024年05月30日 21:55
- */
- @Component
- public class DemoController {
-
- /**
- * Async相当于是方法级别的线程,本身没有自定义线程池更加灵活
- * 相当于是每进来一个请求就开启一个线程,超过核心线程数小于最大线程数放入队列,
- * 队列满了,继续创建线程直至达到最大线程数
- * @throws InterruptedException
- */
- @Async("taskExecutor")
- public void testSync() throws InterruptedException {
- System.out.println(Thread.currentThread().getName());
- Thread.sleep(2000);
- System.out.println("异步执行成功");
- }
- }
