zoukankan      html  css  js  c++  java
  • JDK线程池的拒绝策略

    关于新疆服务请求未带入来话原因的问题

           经核查,该问题是由于立单接口内部没有成功调用接续的 “更新来电原因接口”导致的,接续测更新来电原因接口编码:NGCCT_UPDATESRFLAG_PUT ,立单接口调用代码如下:

    final Map<String, Object> paramsMap = outputObject.getBean();
    paramsMap.put("provCode", provCode);
    paramsMap.put("tenantId", MapUtils.getString(inputObject.getParams(), "tenantId"));
    TaskEngine.getInstance().submit(new Runnable() {
       @Override
       public void run() {
          callContactRel(paramsMap);[zhai1] 
          backWriteWrkfm(paramsMap);
       }
    });

    立单接口中使用起多线程异步调用方式,更新来电原因方法内部记录日志,由于线程内部日志无法在火眼系统查看,当出现该问题时,

    1.多次找在线运维人员查看主机上的日志,均未发现更新来话原因方法内部记录的日志;

    2.登陆csf平台查询该接口的调用记录,根据出现问题的流水号均未查到相关调用记录;

    3.核查调用更新来电原因方法内部catch中如表的错误记录,也未发现问题;

    根据火眼上上下文日志,确定程序一定运行到了启动多线程的地方,遂怀疑线程池的问题,

    该处启用多线程使用的是 TaskEngine工具提供的获取线程池,使用池中资源执行任务。

    经核查TaskEngine类发现该类在初始化的时候会创建一个线程池,核心线程数为1,最大线程数为30的线程池,代码如下:

    private static TaskEngine instance = new TaskEngine();
    public static TaskEngine getInstance() {
    
        return instance;
    
    }
    private TaskEngine() {
    
        executor = new ThreadPoolExecutor(1, 30,180L,
    
                TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadFactory() {
    
            final AtomicInteger threadNumber = new AtomicInteger(1);
    
    
    
            public Thread newThread(Runnable runnable) {
    
                // Use our own naming scheme for the threads.
    
                Thread thread = new Thread(Thread.currentThread().getThreadGroup(), runnable,
    
                        "TaskEngine-pool-" + threadNumber.getAndIncrement(), 0);
    
                // Make workers daemon threads.
    
                thread.setDaemon(true);
    
                if (thread.getPriority() != Thread.NORM_PRIORITY) {
    
                    thread.setPriority(Thread.NORM_PRIORITY);
    
                }
                return thread;
            }
        });
    }

    该线程池构造时尚未指明 拒绝策略 [zhai2] 因此会默认使用 AbortPolicy

    JDK提供的ThreadPoolExecutor 线程池有四种 拒绝策略:

    AbortPolicy 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常。

    CallerRunsPolicy 当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。

    DiscardOldestPolicy 当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。

    DiscardPolicy 当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。

    工程中使用的默认的策略,会不会存在一种情况,在某一个时刻,使用TaskEngine类获取线程池来执行任务时,30个线程同时被使用,导致创建任务数大于最大线程数的限制,该任务将无法被成功执行。

    Demo验证:

    1.使用与项目中相同的线程池执行数据入库操作,模拟设置最大线程数10,核心线程1个,拒绝策略默认:

    @RequestMapping(value = "/testThread")
    
    public String testThread(){
    
        final CommonCfgCode commonCfgCode = new CommonCfgCode();
    
        commonCfgCode.setCodeTypeCd("Thread");
    
        TaskEngine taskEngine = TaskEngine.getInstance();
    
        for(int i=0;i<100;i++){
    
            taskEngine.submit(new Runnable() {
    
                @Override
    
                public void run() {
    
                    testService.save(commonCfgCode);
    
                }
    
            });
    
        }
    
        return "SUCCESS";
    
    }

    循环执行100个任务进行如表操作抛出:

    java.util.concurrent.RejectedExecutionException异常,与该策略描述一致。

    查看如表数据:仅如表10条数据;

     

    2.将拒绝策略修改为:CallerRunsPolicy 其它不变;

    无报错,查询数据:如表100条;(110条中包含使用默认拒绝抛异常策略如表的10条)

     

    Demo git路径:https://git.lug.ustc.edu.cn/zhaiyt/mylife.git

    由于该问题仅在新疆出现,出现的场景无法预知,请各位评审是否可以修改项目中TaskEngine类。


     [zhai1]调用接续接口更新来话原因方法

     [zhai2]线程池的拒绝策略,是指当任务添加到线程池中被拒绝,而采取的处理措施。当任务添加到线程池中之所以被拒绝,可能是由于:第一,线程池异常关闭。第二,任务数量超过线程池的最大限制

  • 相关阅读:
    51 Nod 1068 Bash游戏v3
    51 Nod Bash 游戏v2
    51 Nod 1073 约瑟夫环
    UVA 12063 Zeros and ones 一道需要好好体会的好题
    51 Nod 1161 Partial sums
    2018中国大学生程序设计竞赛
    UVA 11971 Polygon
    UVA 10900 So do you want to be a 2^n-aire?
    UVA 11346 Possibility
    python with as 的用法
  • 原文地址:https://www.cnblogs.com/zhaiyt/p/9897196.html
Copyright © 2011-2022 走看看