SpringBoot | 线程池创建与使用

发布时间 2023-09-27 09:37:39作者: LittleDonkey

欢迎参观我的博客,一个Vue 与 SpringBoot结合的产物:https://poetize.cn

原文链接:https://poetize.cn/article?id=38

线程池的创建方式

Executors.newSingleThreadExecutor():线程只有一个,但是等待队列是Integer.MAX_VALUE

Executors.newCachedThreadPool():核心线程数是0,最大线程数有Integer.MAX_VALUE个,SynchronousQueue没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列

Executors.newFixedThreadPool(5):线程数是指定的,等待队列是Integer.MAX_VALUE

Executors.newSingleThreadScheduledExecutor():核心线程数为1,但是最大线程数为Integer.MAX_VALUE,等待队列是一个延迟无界队列

Executors.newScheduledThreadPool(5):核心线程数是指定的,最大线程数为Integer.MAX_VALUE,等待队列是一个延迟无界队列

自定义线程池

@Configuration
@Slf4j
public class ThreadPoolConfig {

    /**
     * 获取当前系统的CPU 数目
     */
    private static final int CPU_NUMS = Runtime.getRuntime().availableProcessors();

    /**
     * 线程池核心池的大小
     */
    private static final int CORE_POOL_SIZE = CPU_NUMS * 2;

    /**
     * 线程池的最大线程数
     */
    private static final int MAXIMUM_POOL_SIZE = CPU_NUMS * 5;

    @Autowired
    private PoolProperties poolProperties;

    /**
     * 线程池配置
     */
    @Bean(name = "customExecutor")
    public ThreadPoolTaskExecutor customExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程池大小
        threadPoolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        // 最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(MAXIMUM_POOL_SIZE);
        // 队列容量
        threadPoolTaskExecutor.setQueueCapacity(poolProperties.getQueueCapacity());
        // 活跃时间
        threadPoolTaskExecutor.setKeepAliveSeconds(poolProperties.getKeepAliveSeconds());
        // 默认情况下,执行器不会等待任务的终止,它会立即关闭,中断正在进行的任务和清理,剩余的任务队列
        threadPoolTaskExecutor.setAwaitTerminationSeconds(poolProperties.getAwaitTerminationSeconds());
        // 线程名字前缀
        threadPoolTaskExecutor.setThreadNamePrefix(poolProperties.getThreadNamePrefix());
        // CallerRunsPolicy:如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行。
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        threadPoolTaskExecutor.initialize();
        log.info("TreadPoolConfig 创建核心线程数: {}, 最大线程数: {}", CORE_POOL_SIZE, MAXIMUM_POOL_SIZE);
        return threadPoolTaskExecutor;
    }
}

任务提交方式

  • execute():执行一个任务,没有返回值
  • submit():提交一个线程任务,有返回值

submit(Callable<T> task):能获取到它的返回值,通过future.get()获取(阻塞直到任务执行完)。一般使用FutureTask + Callable配合使用。

submit(Runnable task, T result):能通过传入的载体result间接获得线程的返回值。

submit(Runnable task):没有返回值的,就算获取它的返回值也是null

Future.get():会使取结果的线程进入阻塞状态,直到线程执行完成之后,唤醒取结果的线程,然后返回结果

SpringBoot异步方法

  1. 开启:@EnableAsync
  2. 使用:@Async("customExecutor")