springBoot 的默认线程池-ThreadPoolTaskExecutor

Posted 栗子~~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springBoot 的默认线程池-ThreadPoolTaskExecutor相关的知识,希望对你有一定的参考价值。

文章目录

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


springBoot 的默认线程池

01 ThreadPoolTaskExecutor是什么?

hreadPoolTaskExecutor是spring core包中的,
ThreadPoolTaskExecutor是对ThreadPoolExecutor进行了封装,
是sring为我们提供的线程池类。

02 实战

02::01 配置


import com.google.common.util.concurrent.ThreadFactoryBuilder;
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.ThreadPoolExecutor;

/**
 * @author yangzhenyu
 * @version 1.0
 * @description: springBoot 默认线程池
 * @date 2022/9/13 16:56
 */
@Configuration
@EnableAsync
public class ThreadPoolTaskExecutorConfig 
    @Bean("poolTaskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() 
        ThreadPoolTaskExecutor  threadPoolExecutor = new ThreadPoolTaskExecutor();
        threadPoolExecutor = new ThreadPoolTaskExecutor();
        //核心线程数
        threadPoolExecutor.setCorePoolSize(5);
        //最大线程数
        threadPoolExecutor.setMaxPoolSize(5);
        //允许线程最大空闲时间、默认为秒
        threadPoolExecutor.setKeepAliveSeconds(5);
        //缓存队列大小
        threadPoolExecutor.setQueueCapacity(5000);
        //线程池对拒绝任务的处理策略 - 始终抛出RejectedExecutionException
        threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //线程池名前缀
        //threadPoolExecutor.setThreadNamePrefix(THREAD_NAME_PREFIX);
        threadPoolExecutor.setThreadFactory(new ThreadFactoryBuilder().setNameFormat("yzy-Async-%d").build());
        /**
        * taskDecorator主要是对Runnable任务装饰一下, 在任务执行时完成异常日志打印、ThreadLocal清理等功能
         * 但是对Callable任务(由submit()方法提交的任务),这个taskDecorator虽然也能装饰,但是并不能捕获异常,
         * 因为类似FutureTask的run方法内部自己补获了异常,不会抛出到afterExecute方法中
        */
        // 增加 TaskDecorator 属性的配置,解决多线程场景下,获取不到request上下文的问题
        threadPoolExecutor.setTaskDecorator(new MyDecorator());
        threadPoolExecutor.initialize();
        return threadPoolExecutor;
    


当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略, rejectedExecutionHandler 字段用于配置拒绝策略,常用的拒绝策略如下:

  • AbortPolicy:用于被拒绝任务的处理程序,它将抛出 RejectedExecutionException。
  • CallerRunsPolicy:用于被拒绝任务的处理程序,它直接在 execute 方法的调用线程中运行被拒绝的任务。
  • DiscardOldestPolicy:用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试 execute。
  • DiscardPolicy:用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。

import org.slf4j.MDC;
import org.springframework.core.task.TaskDecorator;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.Map;

/**
 * @author yangzhenyu
 * @version 1.0
 * @description:
 * @date 2022/9/13 18:35
 */
public class MyDecorator implements TaskDecorator 

    @Override
    public Runnable decorate(Runnable runnable) 
        RequestAttributes context = RequestContextHolder.currentRequestAttributes();
        Map<String,String> previous = MDC.getCopyOfContextMap();
        return () -> 
            try 
                RequestContextHolder.setRequestAttributes(context);
                if (null != previous)
                    MDC.setContextMap(previous);
                
                runnable.run();
             finally 
                RequestContextHolder.resetRequestAttributes();
                MDC.clear();
            
        ;
    



02::02 使用

我们这里用单元测试来进行测试。

注解式使用:
在使用多线程方法上标注@Async时表明调用的线程池

package com.yzy.task;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @author yangzhenyu
 * @version 1.0
 * @description:
 * @date 2022/9/13 17:11
 */
@Component
@Slf4j
public class Tast 
    //在使用多线程方法上标注@Async时表明调用的线程池
    //注意:一定要在Spring的环境下
    @Async("poolTaskExecutor")
    public  void  testTast() throws InterruptedException 
        log.info("=========== hello ==============");
    



注意:一定要在Spring的环境下

测试:


@RunWith(SpringRunner.class)
@SpringBootTest(classes = ThymeleafDemo.class)
@Slf4j
public class TastTest

    // 注入ThreadPoolTaskExecutor
    @Resource
    private Tast tast;

    //注解式实现
    @Test
    public void ThreadTest_01() throws InterruptedException 
        log.info("测试开始>>>");
        for (int i=0;i<10;i++) 
            tast.testTast();
        
        log.info("测试结束>>>");

    
   

创建并执行线程方式:


@RunWith(SpringRunner.class)
@SpringBootTest(classes = ThymeleafDemo.class)
@Slf4j
public class TastTest


    @Qualifier("poolTaskExecutor")
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    //创建并执行线程方式
    @Test
    public void ThreadTest_02()   
        log.info("测试开始>>>");
        MDC.put("yzy", "yangzhenyu");
        for (int i=0;i<10;i++) 
            //lambda表达式
            threadPoolTaskExecutor.execute(()->
                    System.out.printf("lambda-当前线程%s%n",Thread.currentThread().getName());
            );
        
        log.info("测试结束>>>");

    

以上是关于springBoot 的默认线程池-ThreadPoolTaskExecutor的主要内容,如果未能解决你的问题,请参考以下文章

线程池的学习及使用

springBoot 的默认线程池-ThreadPoolTaskExecutor

springBoot 的默认线程池-ThreadPoolTaskExecutor

springBoot 的默认线程池-ThreadPoolTaskExecutor

Java线程池的选择

SpringBoot项目@Async默认线程池导致OOM问题?