当往一个固定队列ArrayBlockingQueue 不停的提交任务时,会发生什么?

请看如下代码

   private static final int QUEUE_SIZE = 20;private static final int CORE_POOL_SIZE = 2;private static final int MAX_POOL_SIZE = 2;private static final int KEEP_ALIVE_TIME = 5;  public static void main(String[] args) throws Exception {ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(QUEUE_SIZE));while(true) {SenderTask st = new SenderTask();executor.submit(st);}}

  

run完后会发生如下异常:

Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@b99f7c6 rejected from java.util.concurrent.ThreadPoolExecutor@2959ee1d[Running, pool size = 2, active threads = 2, queued tasks = 20, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:110)

如果你有研究过executor的源码你将发现,每次在submit任务的时候,会先进行addWorker()的判断,如果不能添加成功,则会抛出RejectedExecutionException

    public void execute(Runnable command) {if (command == null)throw new NullPointerException();/** Proceed in 3 steps:** 1. If fewer than corePoolSize threads are running, try to* start a new thread with the given command as its first* task.  The call to addWorker atomically checks runState and* workerCount, and so prevents false alarms that would add* threads when it shouldn't, by returning false.** 2. If a task can be successfully queued, then we still need* to double-check whether we should have added a thread* (because existing ones died since last checking) or that* the pool shut down since entry into this method. So we* recheck state and if necessary roll back the enqueuing if* stopped, or start a new thread if there are none.** 3. If we cannot queue task, then we try to add a new* thread.  If it fails, we know we are shut down or saturated* and so reject the task.*/int c = ctl.get();if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);}

以上这个异常还有一种出现的情况就是,当你执行完execute.shutdown()后,任然往executor里提交task,也会抛出该异常

示例代码如下:

 public class RejectedExecutionExceptionExample {public static void main(String[] args) {ExecutorService executor = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(15));Worker tasks[] = new Worker[20];for(int i=0; i<20; i++){tasks[i] = new Worker(i);executor.execute(tasks[i]);}executor.shutdown();     executor.execute(tasks[0]);//继续执行任务}
}

如何解决呢?

1. 控制提交的任务数量,即提交的任务数量不要超过它当前能处理的能力 (这里可以用生产者消费者的模式来解决)

2. 确保不要在shutdown()之后在执行任务

3. 可以用LinkedBlockingQueue代替ArrayBlockingQueue,因为LinkedBlockingQueue可以设成无界的,但是需要注意,设成无界后最终可能发生OOM(内存溢出),

所以要保证第一二点。

参考文献:https://examples.javacodegeeks.com/core-java/util/concurrent/rejectedexecutionexception/java-util-concurrent-rejectedexecutionexception-how-to-solve-rejectedexecutionexception/

转载于:https://www.cnblogs.com/youtianhong/p/6398388.html

RejectedExecutionException 分析相关推荐

  1. Java并发(五)线程池使用番外-分析RejectedExecutionException异常

    Java并发(五)线程池使用番外-分析RejectedExecutionException异常 参考文章: (1)Java并发(五)线程池使用番外-分析RejectedExecutionExcepti ...

  2. 通过了解RejectedExecutionException来分析ThreadPoolExecutor源码

    观看本文章之前,最好看一下这篇文章熟悉下ThreadPoolExecutor基础知识. 1.关于Java多线程的一些常考知识点 2.看ThreadPoolExecutor源码前的骚操作 讲解本篇文章从 ...

  3. SpringBoot源码分析之@Scheduled

    Springboot写上注解@Scheduled就可以实现定时任务, 这里对其源码做一点分析 @Service public class MyScheduled {@Scheduled(cron=&q ...

  4. 一次Dubbo拥堵的分析

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:nxlhero https://blog.51cto.com ...

  5. OOM分析之问题定位(二)

    一.背景 上一篇OOM分析之问题定位(一)中讲到通过单例模式可以有效的减少内存使用.但是随着压测并发数的不断提高,QRCodeTask对象不断增加,内存占用相应也会一直增加.再加上QRCodeTask ...

  6. JAVA线程池的分析和使用

    1. 引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行.第三:提 ...

  7. Netty消息接收类故障案例分析

    <Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析Netty消息接收类故障案例.李林锋此后还将在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的同 ...

  8. java 线程池原理分析

    一.为什么使用线程池 1.降低资源消耗,减少线程创建和销毁次数,每个工作线程可以重复利用,执行多个任务 2.可根据系统承受能力,调整工作线程的数目,防止消耗过多的内存 二.java 线程池使用 Exe ...

  9. 【OkHttp】OkHttp 源码分析 ( 同步 / 异步 Request 请求执行原理分析 )

    OkHttp 系列文章目录 [OkHttp]OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 ) [OkHttp]Android 项目导入 OkHttp ( 配置依赖 | 配置 ...

  10. netty reactor线程模型分析

    netty4线程模型 ServerBootstrap http示例 // Configure the server.EventLoopGroup bossGroup = new EpollEventL ...

最新文章

  1. Linux学习笔记(三)|Vim编辑器
  2. boost::all_clustering_coefficients用法的测试程序
  3. Jerry的WebClient UI 42篇原创文章合集
  4. 转 ABAP_ALV_Function方式与OO方式(较为简单、普通的ALV)
  5. 贪心---移掉K位数字
  6. dj电商-项目开发流程
  7. python炒股日记_自学python的日记分享
  8. CSS3属性transform详解之(旋转:rotate,缩放:scale,倾斜:skew,移动:translate)
  9. 【php导出excel,大量导出,文本格式】
  10. 中国省市SQL表---市级行政单位表
  11. 服务如何获取当前登录的windows用户名
  12. C++和C#结构体转换的问题
  13. c++win32项目 如何显示后再删除一个绘图_以weblogic为中间件,部署一个项目,需如何做?...
  14. Scratch制作飞翔的小喵小游戏
  15. 概率论与数理统计,基础知识、公式、定理、概念(一)
  16. 【学习日记】Dom基础
  17. Python非线性拟合笔记
  18. linux蓝牙obex协议,蓝牙协议英文缩写——记录
  19. 快传号上传视频显示服务器忙,视频如何跨平台上传,快传号如何同时同步很多个小视频?...
  20. windows下修改磁盘扇区数据

热门文章

  1. 科学和工程中的信号处理
  2. 在Windows 下如何使用 AspNetCore Api 和 consul
  3. python之路_自定义forms组件
  4. HNOI2019:My Dream
  5. require.js使用教程
  6. 数据库入门-pymysql模块的使用
  7. Andrew Ng-ML-第十五章-降维
  8. 全网最详细的Windows里下载与安装Sublime Text *(图文详解)
  9. Python学习笔记_零碎知识
  10. Opencv+pycharm+anaconda配置