自定义线程池

一、是有线程池的优点

1、使用线程池可以减少线程的创建和销毁,提高性能!!

2、,每次启动线程,springboot都会从新创建一个线程,线程不重用,显然效率太低,这是因为spring boot自带线程池过于简单,所以在开发中,都会自己配置线程池的属性

二、配置原理

@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {
    //把这个方法的返回对象 交给spring ioc管理
    @Bean//<bean id="getAsyncExecutor" class="">
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //核心线程数:线程池刚创建的时候 就会初始化10个线程
        threadPoolTaskExecutor.setCorePoolSize(10);
        //非核心线程:15-10=5 核心线程不够用的时候
        threadPoolTaskExecutor.setMaxPoolSize(15);
        //缓冲队列的个数 :队列作为一个缓冲的工具,
        //当没有足够的线程去处理任务时,可以将任务放进队列中,以队列先进先出的特性来执行工作任务
        threadPoolTaskExecutor.setQueueCapacity(20);
        //非核心线程数 还回去的时间  如果空闲超过10秒就被回收
        threadPoolTaskExecutor.setKeepAliveSeconds(10);
        //设置线程的前缀名称
        threadPoolTaskExecutor.setThreadNamePrefix("zqs_");
        //用来设置线程池关闭的时候等待所有任务都完成(可以设置时间)
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        //设置上面的时间
        threadPoolTaskExecutor.setAwaitTerminationSeconds(100);
        //拒绝策略:线程池都忙不过来的时候,可以适当选择拒绝
        /**
         *  ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
         * ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
         * ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
         * ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务
         */
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        //初始化线程池
        threadPoolTaskExecutor.initialize();

        return threadPoolTaskExecutor;
    }
}

三、拒绝策略

3.1、队列满了丢任务抛异常(默认)
ThreadPoolExecutor.AbortPolicy()
3.2、队列满了丢任务不抛异常
ThreadPoolExecutor.DiscardPolicy();

这里用的多得是 “广撒网”–》尽管多的发布给用户,推销自己的产品

3.3、将最早进入队列的任务删,之后再尝试加入队列
ThreadPoolExecutor.DiscardOldestPolicy();

这里主要是弹幕问题,弹幕太多,最早的弹幕可能额会提前删除

3.4、添加到线程池失败,那么主线程会自己去执行该任务
ThreadPoolExecutor.CallerRunsPolicy()

这样保证了任务的不会丢失,但是会出现卡顿问题

四、使用修改后的线程

spring boot 自带线程池 springboot中线程池_线程池

五、线程异常(有无返回值的区别)

/**
 * @ClassName
 * @Description TODO
 * @Author ZQS
 * @Date 2020/8/31 0031 22:09
 * @Version 1.0
 **/
@RestController
@Slf4j
public class AsyncController {

    @Autowired
    private AsyncDemo asyncDemo;


    @GetMapping("async1")
    public String async1() throws ExecutionException, InterruptedException {
        asyncDemo.asyncNoResult();
        return "方法调用成功";
    }
    @GetMapping("async2")
    public String async2() throws InterruptedException, ExecutionException {
        Future<String> stringFuture = asyncDemo.asyncResult();
        String s = stringFuture.get();
        log.info("调用有返回值的异步方法"+s);
        return  "方法调用成功";
    }

}
5.1、调用有返回值的线程异常

直接就会报异常出来,控制台或者日志可以看出来

5.2、调用没有返回值的线程异常

如果报异常是不好观察出来的
所以尽量调用没有返回值线程的时候不能写错

5.3、处理

1、线下的时候:通过日志等观察
2、线上的时候:通过发邮箱的方法

最终是以controller层的异常为准