zoukankan      html  css  js  c++  java
  • SpringBoot 线程池配置 实现AsyncConfigurer接口方法

     目的是:
      通过实现AsyncConfigurer自定义线程池,包含异常处理
      实现AsyncConfigurer接口对异常线程池更加细粒度的控制
    *a) 创建线程自己的线程池
      b) 对void方法抛出的异常处理的类AsyncUncaughtExceptionHandler
     

    个人初步理解

     一、线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,
    从而提高效率。如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜。),
    况且还不能控制线程池中线程的开始、挂起、和中止。
    二、利用线程池启动线程
    Thread udpThread = new Thread(udp);
    poolTaskExecutor.execute(udpThread);
    获取当前线程池活动的线程数:
    int count = poolTaskExecutor.getActiveCount();
    logger.debug("[x] - now threadpool active threads totalNum : " +count);
    三、配置解释
    当一个任务通过execute(Runnable)方法欲添加到线程池时:
    1、 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
    2、 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
    3、如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
    4、 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
    也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
    5、 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
    allowCoreThreadTimeout:允许核心线程超时
    rejectedExecutionHandler:任务拒绝处理器

    两种情况会拒绝处理任务:
    当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务
    当线程池被调用shutdown()后,会等待线程池里的任务执行完毕,再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务
    线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy,会抛出异常
    ThreadPoolExecutor类有几个内部实现类来处理这类情况:
    AbortPolicy 丢弃任务,抛运行时异常
    CallerRunsPolicy 执行任务
    DiscardPolicy 忽视,什么都不会发生
    DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务
    实现RejectedExecutionHandler接口,可自定义处理器

    废话不多说 上代码 环境:IDEA +SpringBoot+maven

       一、线程池配置类实现AsyncConfigurer 接口:

    @Component
    public class MyAsyncConfigurer implements AsyncConfigurer {
    
        private static final Logger log = LoggerFactory.getLogger(MyAsyncConfigurer.class);
    
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
            threadPool.setCorePoolSize(2);//当前线程数
            threadPool.setMaxPoolSize(120);// 最大线程数
            threadPool.setQueueCapacity(1);//线程池所使用的缓冲队列
            threadPool.setWaitForTasksToCompleteOnShutdown(true);//等待任务在关机时完成--表明等待所有线程执行完
            threadPool.setAwaitTerminationSeconds(60 * 15);// 等待时间 (默认为0,此时立即停止),并没等待xx秒后强制停止
            threadPool.setThreadNamePrefix("MyAsync-");//  线程名称前缀
            threadPool.initialize(); // 初始化
            System.out.println("--------------------------》》》开启异常线程池");
            return threadPool;
        }
    
    
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    
            return new MyAsyncExceptionHandler();
        }
    
        /**
         * 自定义异常处理类
         * @author hry
         *
         */
        class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    
            //手动处理捕获的异常
            @Override
            public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
                System.out.println("-------------》》》捕获线程异常信息");
                log.info("Exception message - " + throwable.getMessage());
                log.info("Method name - " + method.getName());
                for (Object param : obj) {
                    log.info("Parameter value - " + param);
                }
            }
    
        }

        二、使用简单无参数异步线程进行测试

          

     @Override
        @Async
        public String asyncMethodWithVoidReturnType() {
    
            System.out.println("线程名称:"+Thread.currentThread().getName() + " be ready to read data!");
            try {
                Thread.sleep(1000 * 5);
                System.out.println("---------------------》》》无返回值延迟3秒:");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "已进入到异步";
        }

        三、0--3秒内连续访问如下结果

    线程名称:MyAsync-1 be ready to read data!
    线程名称:MyAsync-2 be ready to read data!
    线程名称:MyAsync-3 be ready to read data!
    线程名称:MyAsync-4 be ready to read data!
    线程名称:MyAsync-5 be ready to read data!
    线程名称:MyAsync-6 be ready to read data!
    线程名称:MyAsync-7 be ready to read data!
    线程名称:MyAsync-8 be ready to read data!
    MyAsync-1---------------------》》》无返回值延迟5秒:
    线程名称:MyAsync-1 be ready to read data!
    MyAsync-2---------------------》》》无返回值延迟5秒:
    线程名称:MyAsync-2 be ready to read data!
    MyAsync-3---------------------》》》无返回值延迟5秒:
    MyAsync-4---------------------》》》无返回值延迟5秒:
    MyAsync-5---------------------》》》无返回值延迟5秒:
    MyAsync-6---------------------》》》无返回值延迟5秒:
    MyAsync-7---------------------》》》无返回值延迟5秒:
    MyAsync-8---------------------》》》无返回值延迟5秒:
    MyAsync-1---------------------》》》无返回值延迟5秒:
    MyAsync-2---------------------》》》无返回值延迟5秒:

         如上可以看出 线程池发挥作用 多个线程访问如果超过核心线程数+队列数 变新创建线程,如果有线程

     空闲下来会继续分配,以此来提高效率。我是利用postMain 来进行的测试,以验证上面所说的理论问题。。

      实际应用中比这个复杂得多。。。。。。。。

         四、如果想要手动捕获异常信息  如下代码 即可

      throw new IllegalArgumentException(s);
    将上面代码 放在需要捕获信息的中
    在线程池配置中 MyAsyncExceptionHandler 的方法中 即会捕捉到信息。。。。。。



    收工。。。。。
  • 相关阅读:
    使用 requests 维持会话
    使用 requests 发送 POST 请求
    使用 requests 发送 GET 请求
    requests 安装
    使用 urllib 分析 Robots 协议
    使用 urllib 解析 URL 链接
    使用 urllib 处理 HTTP 异常
    使用 urllib 处理 Cookies 信息
    使用 urllib 设置代理服务
    按单生产程序发布
  • 原文地址:https://www.cnblogs.com/memoryXudy/p/7737190.html
Copyright © 2011-2022 走看看