美文网首页Java Concurrency
线程池-四种拒绝策略总结

线程池-四种拒绝策略总结

作者: King斌 | 来源:发表于2023-01-16 20:09 被阅读0次

一、线程池的拒绝策略
线程池中,有三个重要的参数,决定影响了拒绝策略:corePoolSize - 核心线程数,也即最小的线程数。workQueue - 阻塞队列 。 maximumPoolSize - 最大线程数
当提交任务数大于 corePoolSize 的时候,会优先将任务放到 workQueue 阻塞队列中。当阻塞队列饱和后,会扩充线程池中线程数,直到达到 maximumPoolSize 最大线程数配置。此时,再多余的任务,则会触发线程池的拒绝策略了。总结起来,也就是一句话,当提交的任务数大于(workQueue.size() + maximumPoolSize ),就会触发线程池的拒绝策略。
二、拒绝策略定义
拒绝策略提供顶级接口 RejectedExecutionHandler ,其中方法 rejectedExecution 即定制具体的拒绝策略的执行逻辑。
jdk默认提供了四种拒绝策略:

  • CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大
  • AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。
  • DiscardPolicy - 直接丢弃,其他啥都没有
  • DiscardOldestPolicy - 当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入

三、测试代码
1、AbortPolicy

public static void main(String[] args) throws Exception{
       int corePoolSize = 5;
       int maximumPoolSize = 10;
       long keepAliveTime = 5;
       BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(10);
       RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
       ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
       for(int i=0; i<100; i++) {
           try {
               executor.execute(new Thread(() -> log.info(Thread.currentThread().getName() + " is running")));
           } catch (Exception e) {
               log.error(e.getMessage(),e);
           }
       }
       executor.shutdown();
   }

executor.execute()提交任务,由于会抛出 RuntimeException,如果没有try.catch处理异常信息的话,会中断调用者的处理流程,后续任务得不到执行(跑不完100个)。可自行测试下,很容易在控制台console中能查看到。
2、CallerRunsPolicy
主体代码同上,更换拒绝策略:

RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

运行后,在控制台console中能够看到的是,会有一部分的数据打印,显示的是 “main is running”,也即体现调用线程处理。
3、DiscardPolicy
更换拒绝策略

RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();

直接丢弃任务,实际运行中,打印出的信息不会有100条。
4、DiscardOldestPolicy
同样的,更换拒绝策略:

RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();

实际运行,打印出的信息也会少于100条。
五、总结
四种拒绝策略是相互独立无关的,选择何种策略去执行,还得结合具体的业务场景。实际工作中,一般直接使用 ExecutorService 的时候,都是使用的默认的 defaultHandler ,也即 AbortPolicy 策略。

相关文章

  • Java线程池拒绝策略

    【Java线程池拒绝任务策略】创建线程池可以指定拒绝策略如下: 一 拒绝时机1) 调用线程池的shutdown函数...

  • 线程池终探

    线程池四种拒绝策略 AbortPolicy 直接抛异常 DiscardPolicy 丢弃不处理 DiscardO...

  • ThreadPoolExecutor

    线程池 拒绝策略 线程池的拒绝策略,即任务被添加到线程池中被拒绝而采取的处理措施。任务被拒绝的原因可能有: 线程池...

  • 多线程juc线程池

    java_basic juc线程池 创建线程池 handler是线程池拒绝策略 排队策略 线程池状态 RUNNIN...

  • 线程池拒绝策略

    jdk默认提供以下四种线程池拒绝策略 AbortPolicy:直接抛出一个RejectedExecutionExc...

  • 面试官:说说你知道多少种线程池拒绝策略

    前言 线程池,相信很多人都有用过,没用过相信的也有学习过。但是,线程池的拒绝策略,相信知道的人会少许多。 四种线程...

  • 线程池-四种拒绝策略总结

    一、线程池的拒绝策略线程池中,有三个重要的参数,决定影响了拒绝策略:corePoolSize - 核心线程数,也即...

  • Java 线程池四种拒绝策略

    jdk1.5版本新增了 JUC 并发包,其中一个包含线程池。 四种拒绝策略: 拒绝策略类型说明1ThreadPoo...

  • ThreadPoolExecutor的RejectedExecu

    java 线程池ThreadPoolExecutor的拒绝策略有: CallerRunsPolicy : 当线程池...

  • 线程池

    线程池执行过程 线程池生命周期 线程池分类 阻塞队列 拒绝策略 - ThreadPoolExecutor.Abor...

网友评论

    本文标题:线程池-四种拒绝策略总结

    本文链接:https://www.haomeiwen.com/subject/tfhwcdtx.html