编程语言   发布时间:2022-06-27  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了线程池的拒绝策略大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
  • 为什么要设计池

    抵消每次获取资源产生的消耗,这种池的设计会初始预设资源,可类比食堂打饭,类似的池设计有线程池、jdbc连接池等,跟池有关的特征包括:池子的初始值、最大值、活跃值等
  • 线程池什么时候触发拒绝策略

    一般是超过池的最大值时触发,但线程连接池还有一个阻塞队列缓冲区,当前提交任务数大于(maxPoolSize + queueCapacity)时就会触发线程池的拒绝策略了。
  • 线程池有哪几种拒绝策略

    一般线程池都是通过RejectedExecutionHandler接口中的rejectedExecution方法实现拒绝策略,一般有四种拒绝策略,分别对应不用方法策略
  1. CallerRunPolicy(调用者策略)
 public static class CallerRunsPolicy implements RejectedExecutionHandler {

        public CallerRunsPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor E) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

当线程池满了后,此拒绝策略会把线程丢给调用者自己处理,适用于对时间要求不高,但是不允许失败的场景 2. AbortPolicy

public static class AbortPolicy implements RejectedExecutionHandler {

        public AbortPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor E) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

线程池的默认拒绝策略,使用任何场景,但是使用时应注意处理好抛出的异常,可能会打断当前执行 3. DiscardPolicy

public static class DiscardPolicy implements RejectedExecutionHandler {

        public DiscardPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor E) {
        }
    }

没使用,就是超出了就不管 4. DiscardOldestPolicy

public static class DiscardOldestPolicy implements RejectedExecutionHandler {

        public DiscardOldestPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor E) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

把最先进入队列的线程抛弃,这个策略使用于消息更新,永远是最新的消息最需要

  • 除了java线程池的拒绝策略,还有哪些其他的拒绝策略 一些开源的框架或者软件也有很好的拒绝策略 比如Dubbo中的
public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {

    protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class);

    private final String threadName;

    private final URL url;

    private static volatile long lastPrintTime = 0;

    private static Semaphore guard = new Semaphore(1);

    public AbortPolicyWithReport(String threadName, URL url) {
        this.threadName = threadName;
        thiS.Url = url;
    }

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor E) {
        String msg = String.format("Thread pool is EXHAUSTED!" +
                        " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +
                        " Executor status:(isShutdown:%s, isTerminated:%s, isTerminaTing:%s), in %s://%s:%d!",
                threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(),
                e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminaTing(),
                url.getProtocol(), url.getIp(), url.getPort());
        logger.warn(msg);
        dumpJStack();
        throw new RejectedExecutionException(msg);
    }

    private void dumpJStack() {
       //省略实现
    }
}

可以看到,当dubbo的工作线程触发了线程拒绝后,主要做了三个事情,原则就是尽量让使用者清楚触发线程拒绝策略的真实原因

  • 输出了一条警告级别的日志,日志内容为线程池的详细设置参数,以及线程池当前的状态,还有当前拒绝任务的一些详细信息。可以说,这条日志,使用dubbo的有过生产运维经验的或多或少是见过的,这个日志简直就是日志打印的典范,其他的日志打印的典范还有spring。得益于这么详细的日志,可以很容易定位到问题所在
  • 输出当前线程堆栈详情,这个太有用了,当你通过上面的日志信息还不能定位问题时,案发现场的dump线程上下文信息就是你发现问题的救命稻草,这个可以参《dubbo线程池耗尽事件-"CyclicBarrier惹的祸"》
  • 继续抛出拒绝执行异常,使本次任务失败,这个继承了JDK默认拒绝策略的特性

大佬总结

以上是大佬教程为你收集整理的线程池的拒绝策略全部内容,希望文章能够帮你解决线程池的拒绝策略所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。