Advertisement

Java线程池拒绝策略详解

  •  5星
  •     浏览量: 0
  •     大小:None
  •      文件类型:PDF


简介:
本文详细解析了Java中线程池的拒绝策略,帮助开发者理解并合理选择或定制适合应用需求的拒绝策略,以优化程序性能。 Java线程池的拒绝策略是指当线程池中的线程数量达到最大值时如何处理新的任务提交的方式。这个策略是由RejectedExecutionHandler接口定义的,并提供了四种默认的拒绝策略:CallerRunsPolicy、AbortPolicy、DiscardPolicy和DiscardOldestPolicy。 首先了解一下线程池的基本概念。线程池是池化思想的应用,其目的是为了提高系统的性能和效率。在Java中,ThreadPoolExecutor类实现了这一功能,它定义了三个重要的参数:corePoolSize(核心线程数)、workQueue(阻塞队列)以及maximumPoolSize(最大线程数)。当提交的任务数量超过(workQueue.size() + maximumPoolSize)时会触发拒绝策略。RejectedExecutionHandler接口中的rejectedExecution方法用于定制具体的执行逻辑。 Java提供了以下四种默认的拒绝策略: 1. **CallerRunsPolicy**:如果任务被拒,只要线程池没有关闭,则使用调用线程直接运行该任务。适合于并发量较小、性能要求不高且不允许失败的情况。 2. **AbortPolicy**:丢弃任务,并抛出RejectedExecutionException异常信息。这是默认的拒绝策略。 3. **DiscardPolicy**:简单地抛弃被拒的任务,不做其他处理。 4. **DiscardOldestPolicy**:如果线程池未关闭且队列非空,则移除最旧的一个任务并尝试重新提交当前新来的任务。 在实际应用中,根据不同的需求可以选择合适的拒绝策略。例如,在高并发情况下使用CallerRunsPolicy可以避免系统资源被过多消耗;需要确保所有任务被执行的情况下则可选用AbortPolicy来抛出异常信息以引起注意。 下面是一个简单的示例代码展示如何配置ThreadPoolExecutor和RejectedExecutionHandler接口实现线程池的拒绝策略: ```java import java.util.concurrent.*; import org.slf4j.*; @Slf4j public class T2 { public static void main(String[] args) throws Exception { int corePoolSize = 5; int maximumPoolSize = 10; long keepAliveTime = 5; BlockingQueue workQueue = new LinkedBlockingQueue<>(10); // 使用AbortPolicy作为拒绝策略 RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler); for (int i = 0; i < 20; ++i) { executor.execute(() -> log.info(执行任务)); } // 等待所有任务完成 executor.shutdown(); executor.awaitTermination(1L, TimeUnit.DAYS); } } ``` 在这个示例中,我们创建了一个ThreadPoolExecutor实例,并设置了AbortPolicy作为拒绝策略。当提交的任务数量超过核心线程数和最大线程数之和时,将会抛出RejectedExecutionException异常信息。

全部评论 (0)

还没有任何评论哟~
客服
客服
  • Java线
    优质
    本文详细解析了Java中线程池的拒绝策略,帮助开发者理解并合理选择或定制适合应用需求的拒绝策略,以优化程序性能。 Java线程池的拒绝策略是指当线程池中的线程数量达到最大值时如何处理新的任务提交的方式。这个策略是由RejectedExecutionHandler接口定义的,并提供了四种默认的拒绝策略:CallerRunsPolicy、AbortPolicy、DiscardPolicy和DiscardOldestPolicy。 首先了解一下线程池的基本概念。线程池是池化思想的应用,其目的是为了提高系统的性能和效率。在Java中,ThreadPoolExecutor类实现了这一功能,它定义了三个重要的参数:corePoolSize(核心线程数)、workQueue(阻塞队列)以及maximumPoolSize(最大线程数)。当提交的任务数量超过(workQueue.size() + maximumPoolSize)时会触发拒绝策略。RejectedExecutionHandler接口中的rejectedExecution方法用于定制具体的执行逻辑。 Java提供了以下四种默认的拒绝策略: 1. **CallerRunsPolicy**:如果任务被拒,只要线程池没有关闭,则使用调用线程直接运行该任务。适合于并发量较小、性能要求不高且不允许失败的情况。 2. **AbortPolicy**:丢弃任务,并抛出RejectedExecutionException异常信息。这是默认的拒绝策略。 3. **DiscardPolicy**:简单地抛弃被拒的任务,不做其他处理。 4. **DiscardOldestPolicy**:如果线程池未关闭且队列非空,则移除最旧的一个任务并尝试重新提交当前新来的任务。 在实际应用中,根据不同的需求可以选择合适的拒绝策略。例如,在高并发情况下使用CallerRunsPolicy可以避免系统资源被过多消耗;需要确保所有任务被执行的情况下则可选用AbortPolicy来抛出异常信息以引起注意。 下面是一个简单的示例代码展示如何配置ThreadPoolExecutor和RejectedExecutionHandler接口实现线程池的拒绝策略: ```java import java.util.concurrent.*; import org.slf4j.*; @Slf4j public class T2 { public static void main(String[] args) throws Exception { int corePoolSize = 5; int maximumPoolSize = 10; long keepAliveTime = 5; BlockingQueue workQueue = new LinkedBlockingQueue<>(10); // 使用AbortPolicy作为拒绝策略 RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler); for (int i = 0; i < 20; ++i) { executor.execute(() -> log.info(执行任务)); } // 等待所有任务完成 executor.shutdown(); executor.awaitTermination(1L, TimeUnit.DAYS); } } ``` 在这个示例中,我们创建了一个ThreadPoolExecutor实例,并设置了AbortPolicy作为拒绝策略。当提交的任务数量超过核心线程数和最大线程数之和时,将会抛出RejectedExecutionException异常信息。
  • 线深度析:七大关键参数、工作原理、创建方法及,以及如何优化线大小
    优质
    本文深入探讨了线程池的核心参数与工作机制,并介绍了其创建方式和拒绝策略。同时提供了关于如何调整线程池规模以优化性能的建议。 线程池是Java多线程编程中的重要概念之一,它通过池化技术有效地管理和控制线程的生命周期,以提高系统资源利用率和性能表现。本段落将深入探讨线程池的核心参数、工作原理、创建方式、拒绝策略以及如何合理分配线程数量。 一、七大核心参数 1. corePoolSize:指定了线程池中始终保持活跃状态的最小线程数。 2. maximumPoolSize:代表了可以同时运行的最大线程数目。 3. keepAliveTime:非核心线程在空闲状态下存活的时间长度,一旦超过此时间则会被销毁。 4. unit:keepAliveTime的时间单位(例如毫秒、分钟等)。 5. workQueue:用于存储等待执行的任务的队列。任务队列可以是有界或无界的类型。 6. threadFactory:线程工厂,负责创建新的线程,并允许自定义设置如命名和优先级等属性。 7. handler:拒绝策略,在线程池与任务队列都满的情况下决定如何处理新提交的任务。 二、工作原理 1. 当一个新任务被提交时,如果当前活跃的线程数少于corePoolSize,则直接创建新的线程来执行该任务。 2. 如果已达到核心线程数量但任务队列尚未填满,那么这个新任务会被放入等待状态中直到有空闲资源可用为止。 3. 当现有工作中的线程数目大于等于corePoolSize,并且此时的任务队列已经满了,则尝试创建新的线程进行处理,直至maximumPoolSize被达到。 4. 如果在最大线程数和任务队列容量都已满的情况下接收新任务,那么根据所设定的拒绝策略来决定如何操作。 三、创建方式 Java提供了ExecutorService接口及Executors类用于构建不同类型的线程池: 1. newFixedThreadPool:固定大小的线程集合。 2. newSingleThreadExecutor:单一线程执行器,确保所有提交的任务按顺序依次完成。 3. newCachedThreadPool:缓存型线程池,允许无限制地创建新线程但会自动回收空闲时间较长的旧线程。 4. newScheduledThreadPool:定时任务调度用的专用线程集合。 四、拒绝策略 1. AbortPolicy:默认情况下采取此行为,即抛出异常并终止执行。 2. CallerRunsPolicy:让调用者直接运行被拒绝的任务(在主线程中)。 3. DiscardPolicy:简单地丢弃新任务而不给出任何指示或反馈信息。 4. DiscardOldestPolicy:放弃队列中最老的未处理请求,以腾出空间给新的提交。 五、合理分配线程池大小 确定合适的线程数需要考虑以下因素: 1. 对于计算密集型的任务而言,理想的线程数量接近CPU核心的数量; 2. 在涉及大量输入/输出操作的应用中可以设置略多一些的并发单位来利用等待期间执行其他任务的机会。 3. 根据具体业务场景调整参数值以匹配最优化性能需求。 4. 考虑到系统资源限制,如内存和磁盘空间等。 综上所述,合理地使用线程池对于提升程序效率至关重要。通过深入理解并掌握上述内容可以帮助开发者编写出更高效且稳定的多线程应用代码,并进一步提高系统的并发处理能力和响应速度。
  • 服务攻击的原理与应对
    优质
    本文深入解析了拒绝服务攻击的工作机制及其危害,并提出了有效的防范和应对措施。 互联网为全世界的人们带来了无限的生机与活力,并真正实现了无国界的全球村概念。然而,在享受这些便利的同时,我们仍然面临许多挑战,如IP地址短缺、大量带宽损耗以及政府规章限制等问题。此外,由于多年来网络系统累积下的无数漏洞,我们现在面临着更大的安全威胁。 潜在攻击者可以利用这些缺口对我们的系统发起恶意行为,并且我们必须为以前的疏忽付出更多的努力来应对这些问题。尽管大多数网络产品都声称具备安全性,但就目前的技术和协议来看,依然存在许多安全隐患。拒绝服务(DoS)攻击是一种全球性的网络安全漏洞,黑客们对此进行了大量研究。 这种类型的攻击已经导致无数网络用户成为受害者,并且一些程序如Tribe Flood Network、tfn2k、smurf以及targa等正在被不断开发出来并散布在网络中,进一步削弱了我们的防护能力。因此,我们急需寻找一种简单易用的安全解决方案来应对这些潜在的威胁。
  • Java ExecutorService线与实例代码
    优质
    本文详细解析了Java中的ExecutorService线程池框架,包括其工作原理、配置方法及最佳实践,并提供了丰富的示例代码以帮助读者深入理解和应用。 本段落详细介绍了Java线程池ExecutorService的相关内容及其在并发编程中的重要性,并提供了实例代码。 首先解释了使用线程池的原因:通过预先创建一定数量的线程并复用,可以有效减少频繁创建与销毁线程带来的性能开销和系统资源消耗。此外,合理调整线程数有助于控制系统的负载水平,避免过多上下文切换导致的问题。 接着介绍了ExecutorService接口及其相对于基础的Executor接口的功能增强:支持关闭操作、任务提交等方法;还说明了Executors工厂类提供的四种不同类型的线程池创建方式: - 固定大小线程池(newFixedThreadPool)。 - 动态调整缓存线程池(newCachedThreadPool),适合短耗时且请求量大的情况。 - 定时调度线程池(newScheduledThreadPool),适用于定时任务执行场景。 - 单一线程执行器(newSingleThreadExecutor)确保按顺序处理所有提交的任务。 最后,通过一个简单的示例展示了如何使用固定大小的线程池来运行多个并发任务。代码中创建了一个包含5个预定义线程的工作队列,并向其添加了若干次迭代循环以模拟具体工作流程,在完成所需操作后调用了shutdown()方法停止接收新请求。 总结而言,Java中的ExecutorService通过优化多线程环境下的资源管理提升了程序的执行效率和稳定性。根据实际需求选择适当的配置选项能够进一步提高应用性能表现。
  • MM审核
    优质
    MM审核策略详解旨在深入解析内容管理与用户提交材料的审查标准及流程,帮助理解并遵守平台规则,确保社区环境健康积极。 本段落通过举例来介绍mm模块的两种标准审批策略:无分类审批策略和含分类审批策略。
  • SAP计划
    优质
    SAP计划策略详解旨在深入剖析企业资源规划系统中的战略规划模块,涵盖目标设定、资源配置及执行监控等关键环节,助力企业管理层制定高效行动计划。 SAP MRP(物料需求计划)的策略在消耗过程中起到关键作用。系统会比较计划独立需求的数量与日期以及实际客户的订单需求。通过将需求管理中的需求类型与销售订单管理系统的需求类型结合起来,可以为每个特定的MRP策略定义一个定制化的消耗过程。这意味着,在维护和输入计划独立需求时,可以通过对比所规定的客户需求类型来确保准确性和一致性。
  • SAP计划
    优质
    SAP计划策略详解旨在深入解析企业资源规划中的关键计划与决策流程,帮助企业优化资源配置、提升运营效率和竞争力。 该文档详细讲解了需求管理中每个计划策略的特点、属性以及使用场景,特别适合初学者阅读。
  • Java线中FutureTask的实现机制
    优质
    本文深入解析了Java线程池中FutureTask的工作原理和实现机制,帮助读者理解异步编程的核心概念。 本段落详细介绍了Java线程池FutureTask的实现原理,内容颇具参考价值,值得需要的朋友阅读借鉴。
  • Java线原理及常见类型
    优质
    本文深入解析Java线程池的工作机制与实现原理,并详细介绍多种常见的线程池类型及其应用场景。 本段落将介绍Java线程池的原理以及几种常见的线程池类型。通过使用线程池可以有效地管理资源、提高响应速度并简化程序设计。 在Java中,创建一个新线程通常需要较多的系统开销,而复用现有的工作线程则更加高效且节省资源。因此,在处理大量并发请求时,使用预先配置好的一组固定大小的工作线程组(即“线程池”)非常有用。当任务到达时,如果所有工作线程都在忙碌,则该任务会被放入队列中等待。 Java提供了多种类型的线程池以满足不同的应用场景需求: 1. **FixedThreadPool**:创建一个固定大小的线程池,在初始化的时候就确定了最大活跃的线程数量,并且在运行过程中不会改变。这种类型适用于负载较稳定的应用场景。 2. **CachedThreadPool**:该种类型的线程池会根据需要动态地添加新的工作线程,但没有固定的线程上限;当空闲时间超过60秒后,多余的空闲线程会被销毁回收资源。适合执行大量短期异步任务的场合。 3. **SingleThreadExecutor**:顾名思义,它使用单个后台线程来运行所有的提交请求,并且保证所有任务按照顺序执行(即在前面的任务完成前不会开始新的任务)。这种方式常用于需要确保操作按序进行的情况。 4. **ScheduledThreadPool**:允许延迟或定期地执行给定的命令。除了支持周期性调度外,它还提供了固定延时和弹性延时两种模式。 以上就是关于Java线程池的一些基本介绍及其类型概述。通过合理选择合适的线程模型可以有效地优化程序性能并提高用户体验。
  • Java中ForkJoinPool线与实例分析
    优质
    本文深入解析了Java中的ForkJoinPool线程池机制,结合实际案例进行详细阐述和代码实现,帮助读者理解并有效运用该技术。 Java线程池ForkJoinPool的实例解析是并发编程中的一个高级主题,在Java 7版本中引入了这种新的线程池实现方式,它能够高效地利用多CPU和多核处理器的优势。 ForkJoinPool的主要优势在于可以将任务分解成多个小的任务,并行地在不同的处理器核心上执行这些子任务;当所有的小任务完成后,再合并结果。这一设计思路非常值得学习和借鉴。 使用ForkJoinPool需要继承自ForkJoinTask类,而该类有两个主要的子类:RecursiveAction(无返回值)与RecursiveTask(有返回值)。在示例代码中,我们采用了一个实例来展示如何利用这些概念进行编程。例如,在一个数组求和的例子中,首先定义了长度为100万且随机填充元素的数组nums;然后创建了一个名为AddTask的任务类继承自RecursiveTask,并实现了计算指定范围内的数组总和的功能。 在具体的实现细节上,如果待处理的数据量较小(小于或等于预设的最大值MAX_NUM),则直接进行求和操作。否则将任务进一步分割为两个子任务分别负责前半部分与后半部分的计算工作,最后合并结果得出最终答案。 ForkJoinPool的主要优点在于可以最大化地利用多核处理器的能力,并减少线程创建及销毁所带来的开销;因为它会复用已存在的线程来执行新的任务。因此,在实际应用中它适用于各种需要高效并发处理的任务场景,如数据处理、科学计算以及图像处理等领域。 总体来说,ForkJoinPool提供了一种高效的解决方案用于实现Java中的并行编程,并且能够显著提升程序在多核处理器环境下的性能表现。