springboot自定义线程池

SpringBoot 自定义线程池_适恒-CSDN博客_springboot自定义线程池

1.我们都知道spring只是为我们简单的处理线程池,每次用到线程总会new 一个新的线程,效率不高,所以我们需要自定义一个线程池。

2.自定义线程池有两种方法,第一种自定义线程池然后使用自己的自定义的,第二种重写spring默认的线程池,然后使用自己重写过的线程池

一:自定义线程池

1.1 修改application.yml

#线程池配置参数
task:
  pool:
    corePoolSize: 5 #设置核心线程数
    maxPoolSize: 20  #设置最大线程数
    keepAliveSeconds: 300 #设置线程活跃时间(秒)
    queueCapacity: 50 #设置队列容量
1.2 线程池配置属性类TaskThreadPoolConfig .java

import org.springframework.boot.context.properties.ConfigurationProperties;
 
/**
 * 线程池配置属性类
 */
@ConfigurationProperties(prefix = “task.pool”)

@Component
public class TaskThreadPoolConfig {
    private int corePoolSize;
 
    private int maxPoolSize;
 
    private int keepAliveSeconds;
 
    private int queueCapacity;
    …getter and setter methods…
}
1.3  注意启动类上一定要开启线程异步支持

@EnableAsync
@EnableConfigurationProperties({TaskThreadPoolConfig.class} ) // 开启配置属性支持
1.4 创建线程池 TaskExecutePool .java

/**
 * 创建线程池配置类
 */
@Configuration
public class TaskExecutePool {
 
    @Autowired
    private TaskThreadPoolConfig config;
 
    /**
     * 1.这种形式的线程池配置是需要在使用的方法上面@Async(“taskExecutor”),
     * 2.如果在使用的方法上面不加该注解那么spring就会使用默认的线程池
     * 3.所以如果加@Async注解但是不指定使用的线程池,又想自己定义线程池那么就可以重写spring默认的线程池
     * 4.所以第二个方法就是重写默认线程池
     * 注意:完全可以把线程池的参数写到配置文件中
     */
 
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(config.getCorePoolSize());
        //最大线程数
        executor.setMaxPoolSize(config.getMaxPoolSize());
        //队列容量
        executor.setQueueCapacity(config.getQueueCapacity());
        //活跃时间
        executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
        //线程名字前缀
        executor.setThreadNamePrefix(“TaskExecutePool-“);
 
        // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
         // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}
1.5 测试方法

 
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @author qijx
 */
@Api(description = “测试控制类11111”)
@RestController
@RequestMapping(“/threadPoolController1”)
public class ThreadPoolController1 {
 
        @Autowired
        private ThreadPoolService1 threadPoolService;
 
 
        @ApiOperation(value = “测试方法”)
        @ResponseBody
        @RequestMapping(value = “/test”,method = RequestMethod.GET)
        public String threadPoolTest() {
            threadPoolService.executeAsync();
            return “hello word!”;
        }
 
 
}
1.6 service测试方法

 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
 
/**
 * @author qijx
 * @date 2019-07-03 17:40
 */
 
@Service
public class ThreadPoolService1 {
    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolService1.class);
 
    @Async(“taskExecutor”) //指定使用那个线程池配置,不然会使用spring默认的线程池
    public void executeAsync() {
        logger.info(“start executeAsync”);
        try {
            System.out.println(“当前运行的线程名称:” + Thread.currentThread().getName());
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info(“end executeAsync”);
    }
 
 
 
}
二:配置默认的线程池

2.1 第一种方式的那个线程池使用时候总要加注解@Async(“taskExecutor”),而这种方式是重写spring默认线程池的方式,使用的时候只需要加@Async注解就可以,不用去声明线程池类。

2.2 这个和上面的TaskThreadPoolConfig类相同,这里不重复

2.3 NativeAsyncTaskExecutePool.java 装配线程池

**
 * 原生(Spring)异步任务线程池装配类,实现AsyncConfigurer重写他的两个方法,这样在使用默认的
 *  线程池的时候就会使用自己重写的
 */
@Slf4j
@Configuration
public class NativeAsyncTaskExecutePool implements AsyncConfigurer{
 
 
    //注入配置类
    @Autowired
    TaskThreadPoolConfig config;
 
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(config.getCorePoolSize());
        //最大线程数
        executor.setMaxPoolSize(config.getMaxPoolSize());
        //队列容量
        executor.setQueueCapacity(config.getQueueCapacity());
        //活跃时间
        executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
        //线程名字前缀
        executor.setThreadNamePrefix(“NativeAsyncTaskExecutePool-“);
 
        // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
 
 
    /**
     *  异步任务中异常处理
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncUncaughtExceptionHandler() {
 
            @Override
            public void handleUncaughtException(Throwable arg0, Method arg1, Object… arg2) {
                log.error(“==========================”+arg0.getMessage()+”=======================”, arg0);
                log.error(“exception method:”+arg1.getName());
            }
        };
    }
}
2.4 测试controller

/**
 * @author qijx
 */
@Api(description = “测试控制类22222”)
@RestController
@RequestMapping(“/threadPoolController2”)
public class ThreadPoolController2 {
        @Autowired
        private ThreadPoolService2 threadPoolService;
 
        @ApiOperation(value = “测试方法”)
        @ResponseBody
        @RequestMapping(value = “/test”,method = RequestMethod.GET)
        public String threadPoolTest() {
            threadPoolService.executeAsync();
            return “hello word!”;
        }
}
2.5 测试service方法

/**
 * @author qijx
 */
 
@Service
public class ThreadPoolService2 {
    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolService2.class);
 
    /**
     * @Async该注解不需要在指定任何bean
     */
    @Async
    public void executeAsync() {
        logger.info(“start executeAsync”);
        try {
            System.out.println(“当前运行的线程名称:” + Thread.currentThread().getName());
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info(“end executeAsync”);
    }
 

    原文作者:hanbingge123
    原文地址: https://blog.csdn.net/hanbingge123/article/details/122924561
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞