1、线程池配置 需要加 @EnableAsync 开启异步线程 或者加载Application.java

说明:setWaitForTasksToCompleteOnShutdown(true)该方法就是这里的关键,用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean,这样这些异步任务的销毁就会先于Redis线程池的销毁。同时,这里还设置了setAwaitTerminationSeconds(60),该方法用来设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。

可以配置多个 @Bean("asyncTaskExecutor") Bean名称不能一样

@Configuration
@EnableAsync	// 开启异步线程
public class AsynConfig {
    
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
       	 	// 核心线程数 线程池维护线程的最少数量
			executor.setCorePoolSize(10);
        	// 最大线程数 线程池维护线程的最大数量
			executor.setMaxPoolSize(20);
        	// 缓存队列 队列最大长度 >=mainExecutor.maxSize
			executor.setQueueCapacity(200);
        	// 线程池维护线程所允许的空闲时间 
			executor.setKeepAliveSeconds(60);
        	// 线程前缀名称
			executor.setThreadNamePrefix("defaultExecutor-");
        	// 线程池对拒绝任务(无线程可用)的处理策略
			executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
			executor.setWaitForTasksToCompleteOnShutdown(true);
			executor.setAwaitTerminationSeconds(60);
			return executor;
    }
    
    @Bean("asyncTaskExecutor")
    public Executor asyncTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
       	 	// 核心线程数 线程池维护线程的最少数量
			executor.setCorePoolSize(10);
        	// 最大线程数 线程池维护线程的最大数量
			executor.setMaxPoolSize(20);
        	// 缓存队列 队列最大长度 >=mainExecutor.maxSize
			executor.setQueueCapacity(200);
        	// 线程池维护线程所允许的空闲时间 
			executor.setKeepAliveSeconds(60);
        	// 线程前缀名称
			executor.setThreadNamePrefix("asyncTaskExecutor-");
        	// 线程池对拒绝任务(无线程可用)的处理策略
			executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
			executor.setWaitForTasksToCompleteOnShutdown(true);
			executor.setAwaitTerminationSeconds(60);
			return executor;
    }
}

TestService

import java.util.concurrent.Future;

public interface TestService {
    
    /**
     * 异步调用,无返回值
     */
    void asyncTask();

    /**
     * 异步调用,有返回值
     */
    Future<String> asyncTask(String s);
}

TestServiceImpl

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import java.util.concurrent.Future;

@Service
public class TestServiceImpl implements TestService {

    @Async
    @Override
    public void asyncTask() {
        long startTime = System.currentTimeMillis();
        try {
            //模拟耗时
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + ":void asyncTask(),耗时:" + (endTime - startTime));
    }

    @Async("asyncTaskExecutor")
    @Override
    public Future<String> asyncTask(String s) {
        long startTime = System.currentTimeMillis();
        try {
            //模拟耗时
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + ":Future<String> asyncTask(String s),耗时:" + (endTime - startTime));
        return AsyncResult.forValue(s);
    }
}