当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

当Executor已经关闭(即执行了executorService.shutdown()方法后),并且Executor将有限边界用于最大线程和工作队列容量,且已经饱和时,在方法execute()中提交的新任务将被拒绝.
在以上述情况下,execute 方法将调用其 RejectedExecutionHandler 的RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) 方法。

线程池默认会采用的是defaultHandler策略。首先看defaultHandler的定义:

private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); // 使用默认的拒绝策略 
//丢弃任务并抛出RejectedExecutionException异常。
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());  }
}

如下是一个测试任务的例子,下面编写4个测试用例来测试。

class MyRunnable implements Runnable {  private String name;  public MyRunnable(String name) {  this.name = name;  }  @Override  public void run() {  try {  System.out.println(this.name + " is running.");  Thread.sleep(100);  } catch (Exception e) {  e.printStackTrace();  }  }
}

看一下其他拒绝策略的具体实现。

  • 1.DiscardPolicy 示例(也是丢弃任务,但是不抛出异常。)
public class DiscardPolicyDemo {  private static final int THREADS_SIZE = 1;  private static final int CAPACITY = 1;  public static void main(String[] args) throws Exception {  // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。  ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY));  // 设置线程池的拒绝策略为"丢弃"  pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());  // 新建10个任务,并将它们添加到线程池中。  for (int i = 0; i < 10; i++) {  Runnable myrun = new MyRunnable("task-"+i);  pool.execute(myrun);  }  // 关闭线程池  pool.shutdown();  }
}

线程池pool的”最大池大小”和”核心池大小”都为1(THREADS_SIZE),这意味着”线程池能同时运行的任务数量最大只能是1”。
线程池pool的阻塞队列是ArrayBlockingQueue,ArrayBlockingQueue是一个有界的阻塞队列,ArrayBlockingQueue的容量为1。这也意味着线程池的阻塞队列只能有一个线程池阻塞等待。   
根据”“中分析的execute()代码可知:线程池中共运行了2个任务。第1个任务直接放到Worker中,通过线程去执行;第2个任务放到阻塞队列中等待。其他的任务都被丢弃了!

  • 2.DiscardOldestPolicy 示例(丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程))
public class DiscardOldestPolicyDemo {  private static final int THREADS_SIZE = 1;  private static final int CAPACITY = 1;  public static void main(String[] args) throws Exception {  // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。  ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,  new ArrayBlockingQueue<Runnable>(CAPACITY));  // 设置线程池的拒绝策略为"DiscardOldestPolicy"  pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());  // 新建10个任务,并将它们添加到线程池中。  for (int i = 0; i < 10; i++) {  Runnable myrun = new MyRunnable("task-"+i);  pool.execute(myrun);  }  // 关闭线程池  pool.shutdown();  }
}

运行结果:

task-0 is running.
task-9 is running.

将”线程池的拒绝策略”由DiscardPolicy修改为DiscardOldestPolicy之后,当有任务添加到线程池被拒绝时,线程池会丢弃阻塞队列中末尾的任务,然后将被拒绝的任务添加到末尾。

  • 3.AbortPolicy 示例(丢弃任务并抛出RejectedExecutionException异常。)
public class AbortPolicyDemo {  private static final int THREADS_SIZE = 1;  private static final int CAPACITY = 1;  public static void main(String[] args) throws Exception {  // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。  ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,  new ArrayBlockingQueue<Runnable>(CAPACITY));  // 设置线程池的拒绝策略为"抛出异常"  pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());  try {  // 新建10个任务,并将它们添加到线程池中。  for (int i = 0; i < 10; i++) {  Runnable myrun = new MyRunnable("task-"+i);  pool.execute(myrun);  }  } catch (RejectedExecutionException e) {  e.printStackTrace();  // 关闭线程池  pool.shutdown();  }  }
}

(某一次)运行结果:

java.util.concurrent.RejectedExecutionExceptionat java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1774)at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:768)at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:656)at AbortPolicyDemo.main(AbortPolicyDemo.java:27)
task-0 is running.
task-1 is running.

将”线程池的拒绝策略”由DiscardPolicy修改为AbortPolicy之后,当有任务添加到线程池被拒绝时,会抛出RejectedExecutionException。

  • 4.CallerRunsPolicy 示例(由调用线程处理该任务)
public class CallerRunsPolicyDemo {  private static final int THREADS_SIZE = 1;  private static final int CAPACITY = 1;  public static void main(String[] args) throws Exception {  // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。  ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,  new ArrayBlockingQueue<Runnable>(CAPACITY));  // 设置线程池的拒绝策略为"CallerRunsPolicy"  pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());  // 新建10个任务,并将它们添加到线程池中。  for (int i = 0; i < 10; i++) {  Runnable myrun = new MyRunnable("task-"+i);  pool.execute(myrun);  }  // 关闭线程池  pool.shutdown();  }
}

(某一次)运行结果:

task-2 is running.
task-3 is running.
task-4 is running.
task-5 is running.
task-6 is running.
task-7 is running.
task-8 is running.
task-9 is running.
task-0 is running.
task-1 is running.

将”线程池的拒绝策略”由DiscardPolicy修改为CallerRunsPolicy之后,当有任务添加到线程池被拒绝时,线程池会将被拒绝的任务添加到”线程池正在运行的线程”中取运行。

参考来自http://blog.csdn.net/zhoufenqin/article/details/51012666

Java线程池--拒绝策略RejectedExecutionHandler相关推荐

  1. java线程池拒绝策略_Java核心知识 多线程并发 线程池原理(二十三)

    线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后 启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕, 再从队列中取出任务来执行.他 ...

  2. 线程池拒绝策略-RejectedExecutionHandler

    ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常. ThreadPoolExecutor.DiscardPolicy ...

  3. java线程池拒绝策略_Java线程池ThreadPoolExecutor的4种拒绝策略

    最近在做大批量数据采集转换工作,基础数据在本地但是需要调用网络资源完成数据转换.多方面原因在保证良好运行情况下,最多开5个线程进行网络资源调用.方案是基础数据在数据库分页,循环遍历每一条数据,创建调用 ...

  4. 【Java 并发编程】线程池机制 ( 线程池阻塞队列 | 线程池拒绝策略 | 使用 ThreadPoolExecutor 自定义线程池参数 )

    文章目录 一.线程池阻塞队列 二.拒绝策略 三.使用 ThreadPoolExecutor 自定义线程池参数 一.线程池阻塞队列 线程池阻塞队列是线程池创建的第 555 个参数 : BlockingQ ...

  5. 线程池拒绝策略 开发中常用什么策略_面试官:说说你知道多少种线程池拒绝策略...

    往期文章 为什么阿里Java规约要求谨慎使用SimpleDateFormathttps://www.toutiao.com/i6696127929048367629/ 为什么我强烈推荐你用枚举来实现单 ...

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

    前言 线程池,相信很多人都有用过,没用过相信的也有学习过.但是,线程池的拒绝策略,相信知道的人会少许多. 四种线程池拒绝策略 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPool ...

  7. 【多线程】线程池拒绝策略详解与自定义拒绝策略

    线程池的拒绝策略 ThreadPoolExecutor内部有实现4个拒绝策略,默认为AbortPolicy策略 CallerRunsPolicy:由调用execute方法提交任务的线程来执行这个任务 ...

  8. 自定义线程池拒绝策略缓解高并发下线程池压力

    一. 默认的拒绝策略 ThreadPoolExceutor.AbortPolicy : 丢弃任务并抛出RejectedExecutionException异常.         ThreadPoolE ...

  9. 自定义线程池拒绝策略

    一. 默认的拒绝策略         ThreadPoolExceutor.AbortPolicy : 丢弃任务并抛出RejectedExecutionException异常.         Thr ...

最新文章

  1. 独家 | 菜鸟必备的循环神经网络指南(附链接)
  2. MySQL中MyISAM 与innoDB的区别(转)
  3. setHeadAndPropagate
  4. 关于烂代码的那些事——什么是好代码
  5. 如何为CSS指定对应的Media type
  6. http --- 前端的缓存
  7. Windows终端利器Cmder
  8. 《MySQL——join语句优化tips》
  9. 第五章 条件、循环及其他语句
  10. 【Python自然语言处理】中文分词技术——规则分词
  11. qt给qdialog加一个滚动条_这些小程序技巧,你敢说你一个用不到?
  12. vue.js点击更多加载更多数据,双数组合并
  13. MVC中modelstate的使用
  14. Prometheus Alertmanager报警组件
  15. 视觉媒体通信作业记录(四)视频网络传输
  16. sprintf 函数的详解
  17. 主菜单在c语言中的作用,C语言 如何实现返回主菜单????
  18. 我用20种编程语言送上新年的祝福,Happy new year!
  19. k-means聚类算法——c语言
  20. JDK中的Hprof命令

热门文章

  1. 聊聊工业界做机器学习的里程碑
  2. 25+AI技术主题演讲及项目展示!英特尔AI全球影响力嘉年华开启,全球AI人才线上群聚
  3. 从用户反馈的可解释性提升推荐模型
  4. 2020年搜索推荐系统论文干货集锦
  5. javascript   卸载事件(onunload)
  6. Linux内核:关于中断你需要知道的【转】
  7. ConcurrentSkipListMap深入分析
  8. HDU1164 Eddy's research I【素因子分解】
  9. android-apt-compiler: Cannot run program D:\android-sdk\platform-tools\aapt
  10. JavaScript内核系列 第8章 面向对象的JavaScript(下)