首页 > 编程语言 >java.util.concurrent.RejectedExecutionException异常分析

java.util.concurrent.RejectedExecutionException异常分析

时间:2023-12-08 17:00:25浏览次数:37  
标签:RejectedExecutionException --- java 队列 util corePoolSize 任务 线程 maximumPoolSize

感谢:https://blog.csdn.net/wzy_1988/article/details/38922449

核心池和最大池的大小

graph TB A("提交新任务") -->G{"maximumPoolSize设置为<br/>无界值<br/>(例如:Integer.MAX_VALUE)"} G --- |"无界值"| H["允许线程池适应任意数量的并发任务"] G --- |"有界值"| B{"corePoolSize 和 <br/>maximumPoolSize相同"} B --- |"相同"| C["创建了固定大小的线程池"] B --- |"不同"| D{"运行的线程数:x"} D --- |"x < corePoolSize"| E["创建新线程来处理请求,即使其他辅助线程是空闲的"] D --- |"corePoolSize < x < maximumPoolSize"| F["仅当队列满时才创建新的线程"]

保持活动时间

如果池中当前有多于corePoolSize的线程,则这些多出的线程在空闲时间超过keepAliveTime时将会终止。

排队

所有BlockingQueue都可用于传输和保持提交的任务。可以使用此队列与池大小进行交互:

graph TB A("运行的线程数:x") --> B{"提交任务"} B --- |"x < corePoolSize"| C["Executor始终首选添加新的线程,而不进行排队"] B --- |"x >= corePoolSize"| D["Executor始终首选将请求加入队列,而不添加新的线程"] D --> E{"将请求加入队列"} E --- |"成功"| F["队列+1"] E --- |"失败"| G{"创建新的线程"} G --- |"成功"| I["线程+1"] G --- |"失败"| J["创建此线程超出maximumPoolSize,任务将被拒绝(抛出RejectedExecutionException)"]

排队有三种通用策略:

  1. 直接提交:工作队列的默认选项是synchronousQueue,它将任务直接提交给线程而不保持它们。在此,如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。此策略可以避免在处理可能具有内部依赖性的请求集时出现锁。直接提交通常要求无界maximumPoolSizes以避免拒绝新提交的任务。当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增加的可能性。

  2. 无界队列:使用无界队列(例如,不具有预定义容量的LinkedBlockingQueue)将导致在所有corePoolSize线程都忙时新任务在队列中等待。这样,创建的线程就不会超过corePoolSize(因此,maximumPoolSize的值也就无效了)。

  3. 有界队列:当使用有限的maximumPoolSizes时,有界队列(如ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折中:使用大型队列和小型池可以最大限度的降低CPU使用率、操作系统资源和上下文切换开销,但是可能导致人工降低吞吐量。如果任务频繁阻塞,则系统可能为超过您许可的更多线程安排时间,使用小型队列通常要求较大的池大小,CPU使用率较高,但是可能遇到不可接受的调度开销,这样可会降低吞吐量。

终止

程序不再引用的池没有剩余线程会自动shutdown。如果希望确保回收取消引用的池(即使用户忘记调用shutdown()),则必须安排未使用的线程最终终止。

异常原因

  1. 线程池显示的调用了shutdown()之后,再向线程池提交任务的时候,如果你配置的拒绝策略是ThreadPoolExecutor.AbortPolicy的话,这个异常就被会抛出来。

  2. 当你的排队策略为有界队列,并且配置的拒绝策略是ThreadPoolExecutor.AbortPolicy,当线程池的线程数量已经达到了maximumPoolSize的时候,你再向它提交任务,就会抛出ThreadPoolExecutor.AbortPolicy异常。

解决方案

  1. 尽量调大maximumPoolSize,例如设置为Integer.MAX_VALUE
  2. 使用其他排队策略,例如LinkedBlockingQueue
  3. 调大队列(ArrayBlockingQueue)的大小

标签:RejectedExecutionException,---,java,队列,util,corePoolSize,任务,线程,maximumPoolSize
From: https://www.cnblogs.com/wywblogs/p/17888546.html

相关文章

  • java使用Ffmpeg合成音频和视频
    1、Maven依赖<!--需要注意,javacv主要是一组API为主,还需要加入对应的实现--><dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.5.6</version>&......
  • java-导出pdf
    前言:  纯代码画pdf格式<!--iTextPDF--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.2</version></......
  • Java中<where>和<if>标签的组合使用
    在Java中,并没有<where>和<if>标签的组合使用。这两个标签不是Java编程语言或Java标准库的一部分,它们可能是你所使用的特定框架或库提供的自定义标签。如果你正在使用某个特定的Java框架或模板引擎(如MyBatis、Thymeleaf等),这些框架或引擎可能提供了自定义标签,使得在代码中使用类似于<......
  • JetBrains WebStorm 2023.3 (macOS, Linux, Windows) - 最智能的 JavaScript IDE
    JetBrainsWebStorm2023.3(macOS,Linux,Windows)-最智能的JavaScriptIDE请访问原文链接:https://sysin.org/blog/jb-webstorm-2023/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgJetBrainsWebStorm-最智能的JavaScriptIDEWebStorm是一个适用于JavaSc......
  • 使用Java实现面向对象编程 第八章 File IO 总结笔记
    java里操作文件1.第一步一定是获得这个文件(获得的文件,你是无法解析获得里面的内容,约等于获得冰。你只能知道大小颜色等。外表能够获取信息.)。2.第二步获得这个文件将这个文件转换成流。然后从这个io流里读取数据io流里又分为字符流(专门处理文字)字节流(专门处理2进制等文件)3.......
  • 如何实现Java file.mkdir()失败的具体操作步骤
    如何实现Javafile.mkdir()失败的具体操作步骤Java中的file.mkdir()失败问题解析在Java中,使用file.mkdir()方法可以创建一个新的文件夹。然而,有时候我们可能会遇到file.mkdir()失败的情况,这可能导致程序没有按照预期创建文件夹。本篇文章将详细解析file.mkdir()失败的原因,并提供......
  • Java Agent有什么作用?
     JavaAgent概述JavaAgent是一种特殊类型的软件组件,它允许在Java虚拟机(JVM)运行时修改应用程序的字节码。这种技术通常用于性能监控、日志记录、系统调试等。JavaAgent主要分为两类:1.启动时加载的Agent(Pre-MainAgent)这种类型的Agent在应用程序的主方法(main)执行之前加载......
  • java实例化的五种方式
    1.创建新对象五种方式1.用new语句创建对象,这是最常见的创建对象的方法。2.使用Class类的newInstance方法3.使用Constructor类的newInstance方法运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。如:Objectobj=Class.forName("java......
  • Java synchronized
    synchronized是Java中最基本的线程同步机制之一,通过在方法或代码块上添加synchronized关键字,可以确保只有一个线程可以访问该方法或代码块。它是Java中实现线程安全的重要机制之一。synchronized关键字的使用方式有两种:1、修饰实例方法当synchronized关键字修饰一个实例方法时,......
  • Java synchronized 、ReentrantLock和Semaphore
    synchronized在Java中,使用synchronized关键字可以实现对代码块或方法的同步访问,以确保多个线程不会同时访问共享资源。当一个线程获取了对象的锁(即进入了synchronized代码块),其他线程如果也希望获取该对象的锁,它们将被阻塞,直到拥有锁的线程执行完毕并释放锁。因此,在某种意义上,使......