关于SpringBoot中多线程的两个注解:
@Async是spring为了方便开发人员进行异步调用而出现的。在方法上加入这个注解,spring会从线程池中获取一个新的线程来执行方法,实现异步调用
@EnableAsync表示开启对异步任务的支持,可以放在SpringBoot的启动类上,也可以放在自定义的配置上。

一:最简单的使用

在springBoot项目中,直接在启动类上加上@EnableAsync,然后在service层的方法上加上@Async,那么当controller调用该方法的时候,就会在主线程外自动新建线程执行该方法。

1.springboot启动类开启异步支持

在springboot项目中,直接在启动类上加上@EnableAsync,然后在service层方法上对于需要异步调用的方法加上@Async,那么当controller层调用这个方法的时候,就会在主线程外自动新建新建线程执行该方法

@EnableAsync//开启异步任务支持
@SpringBootApplication
public class ThreadDemoApplication{
	public static void main(String[] args){
	SpringApplication.run(ThreadDemoApplication.class,args);
	}
}

2、在service中编写测试方法

@Service
public class MutiThreadTest {

    @Async
    public void add() throws InterruptedException {
        for (int i=0;i<=100;i++){
            System.out.println(Thread.currentThread().getName()+":"+LocalDateTime.now().toLocalTime());
            Thread.sleep(1000);
        }
    }
    @Async
    public void sub() throws InterruptedException {
        for (int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+ LocalDateTime.now().toLocalTime());
            Thread.sleep(2000);
        }
    }
}

编写测试类

@Component
public class TestScheduleApplication implements ApplicationRunner {
    @Autowired
    MutiThreadTest mutiThreadTest;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(Thread.currentThread().getName());
//        Thread.sleep(10000);
//        System.out.println("sleep结束");
        mutiThreadTest.sub();
        mutiThreadTest.add();
    }
}

如果没有自定义线程池@Async默认的线程池是SimpleAsyncTaskExecutor

三.自定义线程池来使用@Async

1、新建一个线程池配置类,在配置类上加@EnableAsync,不用在启动类上加,可以配置不同的线程池,用bean的name做区分

@Configuration //让spring扫描到
@EnableAsync
public class ThreadConfig {

    @Bean(name = "pool1")
    public Executor createExecutor(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(1);//核心线程数(默认线程数)
        threadPoolTaskExecutor.setMaxPoolSize(5);//最大线程数
        threadPoolTaskExecutor.setKeepAliveSeconds(60);//允许线程空闲时间(单位:默认为秒)
        threadPoolTaskExecutor.setQueueCapacity(200);//缓冲队列数
        threadPoolTaskExecutor.setThreadNamePrefix("Thread-0");//线程池名前缀
        //线程池对拒绝任务的处理策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        return threadPoolTaskExecutor;
    }


    @Bean(name = "pool2")
    public ThreadPoolTaskExecutor createExecutor2(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(1);//核心线程数(默认线程数)
        threadPoolTaskExecutor.setCorePoolSize(5);//最大线程数
        threadPoolTaskExecutor.setKeepAliveSeconds(60);//允许线程空闲时间(单位:默认为秒)
        threadPoolTaskExecutor.setQueueCapacity(200);//缓冲队列数
        threadPoolTaskExecutor.setThreadNamePrefix("Thread-1");//线程池名前缀
        //线程池对拒绝任务的处理策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        return threadPoolTaskExecutor;
    }
}

2、@Async的使用一样是在service层的方法上加,如果配置了多个线程池,可以用@Async("name"),那么表示线程池的@Bean的name,来指定用哪个线程池来处理
假如只配置了一个线程池,直接用@Async就会用自定义的线程池执行
加入配置了多个线程池,用@Async没有指定用哪个线程池,会默认的SimpleAsyncTaskExecutor来处理

/**
 * @Author: LS
 * @Date: 2022 - 08 - 18 - 9:22
 * @Description: 自定义多线程线程池
 * @version: 1.0
 */
@Component
public class MutiThreadTest1 {

    @Async("pool1")
    public void method1() throws InterruptedException {
        for (int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+ LocalDateTime.now().toLocalTime()+"====="+i);
//            Thread.sleep(1000);
        }
    }

    @Async("pool2")
    public void method2(){
        for (int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+LocalDateTime.now().toLocalTime()+"----"+i);
        }
    }

    @Async("pool1")
    public  void  method3(){
        for (int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+ LocalDateTime.now().toLocalTime()+"////"+i);
        }
    }
}

3、测试类

@Component
public class TestScheduleApplication implements ApplicationRunner {
    @Autowired
    MutiThreadTest mutiThreadTest;

    @Autowired
    MutiThreadTest1 mutiThreadTest1;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(Thread.currentThread().getName());
//        Thread.sleep(10000);
//        System.out.println("sleep结束");
//        mutiThreadTest.sub();
//        mutiThreadTest.add();
        mutiThreadTest1.method1();
        mutiThreadTest1.method2();
        mutiThreadTest1.method3();
    }
}