线程池的拒绝策略

发布时间:2023年12月28日

在这里插入图片描述

线程池拒绝策略

线程池的拒绝策略是指当任务添加到线程池中被拒绝时,采取的处理措施。

当任务添加到线程池中之所以被拒绝,可能是由于线程池异常关闭或者任务数量超过线程池的最大限制。

线程池共包括4种拒绝策略,它们分别是:AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy和DiscardPolicy。具体来说:

  1. AbortPolicy:当任务添加到线程池中被拒绝时,它将抛出RejectedExecutionException异常。
  2. CallerRunsPolicy:当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。
  3. DiscardOldestPolicy:当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。
  4. DiscardPolicy:当任务添加到线程池中被拒绝时,线程池会直接丢弃这个任务。

线程池的默认拒绝策略是AbortPolicy。当任务被拒绝时,它会抛出RejectedExecutionException异常。

在选择适当的策略时,需要权衡多种因素,如系统的可靠性要求、资源使用情况和任务性质等。

在这里插入图片描述

拒绝策略工作模式

以下是这四种策略的具体工作方式:

  1. AbortPolicy:当任务被拒绝时,会直接抛出RejectedExecutionException异常。这是一种比较直接的处理方式,可以让调用者感知到任务被拒绝,然后根据业务逻辑选择重试或者放弃提交等策略。
  2. DiscardPolicy:如其名字所述,当新任务被提交后直接被丢弃,并且不会有任何通知。这意味着在提交任务时可能并不知道任务已被丢弃,从而可能造成数据丢失。
  3. DiscardOldestPolicy:如果线程池未关闭且没有能力执行任务,则会丢弃等待队列中最旧的未处理任务,通常是存活时间最长的任务,然后将拒绝的任务添加到等待队列中。这种方式可以腾出空间给新提交的任务,但同样也存在数据丢失的风险。
  4. CallerRunsPolicy:当有新任务提交后,如果线程池未关闭且没有能力执行,则把这个任务交于提交任务的线程执行。这样做的好处是新提交的任务不会被丢弃,也不会造成业务损失。同时,由于提交任务的线程需要负责执行任务,因此在任务执行期间,该线程不会被释放,从而减缓了任务提交的速度,相当于是一个负反馈。

在这里插入图片描述

如何自定义拒绝策略

自定义线程池的拒绝策略可以通过实现RejectedExecutionHandler接口并覆盖其rejectedExecution方法来实现。以下是一个简单的示例:

ThreadPoolExecutor.RejectedExecutionHandler handler = new ThreadPoolExecutor.RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 在这里处理任务被拒绝的情况
        // 可以选择记录日志、抛出异常、执行备选方案等
    }
};

然后,将这个自定义的拒绝策略设置给线程池:

ThreadPoolExecutor executor = new ThreadPoolExecutor(...);
executor.setRejectedExecutionHandler(handler);

这样,当任务被线程池拒绝时,就会调用自定义的拒绝策略进行处理。具体如何处理,取决于rejectedExecution方法中的实现。

在这里插入图片描述

自定义拒绝策略中添加异常处理

在自定义线程池的拒绝策略中添加异常处理,可以在rejectedExecution方法中抛出异常。例如,可以抛出一个自定义的异常类,该类继承自RuntimeExceptionException

以下是一个示例,演示如何在自定义拒绝策略中添加异常处理:

ThreadPoolExecutor.RejectedExecutionHandler handler = new ThreadPoolExecutor.RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 在这里处理任务被拒绝的情况,并抛出自定义的异常
        throw new MyCustomRejectedException("Task rejected from thread pool.");
    }
};

在这个示例中,我们创建了一个名为MyCustomRejectedException的自定义异常类,该类继承自RuntimeException。当任务被线程池拒绝时,我们在rejectedExecution方法中抛出这个自定义异常。

请注意,自定义的异常类可以根据实际需求进行设计和实现。你可以选择继承自RuntimeExceptionException,并在异常类中添加适当的字段和构造函数来记录和传递更多关于任务被拒绝的信息。

在这里插入图片描述

线程池的优缺点

线程池的优点主要有:

  1. 降低资源消耗:通过重复利用已创建的线程,降低线程创建和销毁造成的消耗。
  2. 提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控。

线程池的缺点主要有:

  1. 线程数量限制:由于线程池中的线程数量是有限的,如果提交的任务数量超过了线程池的最大容量,那么新提交的任务将无法被处理,需要等待其他任务执行完毕才能被处理。
  2. 无法充分利用多核资源:如果线程池中的线程数量设置过少,而服务器又具有多个处理器核心,那么可能无法充分利用服务器的多核资源,导致性能浪费。
  3. 任务的执行顺序不确定:在线程池中,任务的执行顺序是不确定的,这可能会导致一些任务得不到及时处理,或者处理结果不符合预期。
  4. 无法处理大量阻塞任务:如果线程池中的任务存在大量的阻塞操作(如IO操作),那么这些阻塞任务会占用线程池中的线程,导致其他任务无法得到及时处理。

线程池在降低资源消耗和提高响应速度等方面具有优势,但也存在一些缺点需要注意。在实际应用中,需要根据具体情况选择是否使用线程池以及如何配置线程池参数。

线程池配置策略

线程池的配置策略是指根据任务特性和系统环境等因素,合理地配置线程池的参数,以实现高效的任务处理和资源利用。合理的线程池配置策略可以提高系统的吞吐量、响应性能和稳定性。

在配置线程池时,需要考虑多个因素,如任务的性质、优先级、执行时间和依赖性等。根据任务性质的不同,可以分为CPU密集型任务、IO密集型任务和混合型任务。针对不同类型的任务,需要配置不同规模的线程池,以充分利用系统资源并提高任务处理效率。

除了任务性质,任务的优先级和执行时间也是配置线程池时需要考虑的因素。高优先级任务需要优先处理,而长执行时间任务则需要更多的线程来并行处理。此外,任务的依赖性也是一个重要因素,如果任务依赖其他系统资源,如数据库连接,则需要在配置线程池时加以考虑。

合理的线程池配置策略可以有效地提高系统的性能和响应速度,同时还可以降低系统的负载和资源消耗。因此,在系统设计和开发过程中,需要根据实际情况选择合适的线程池配置策略,并进行相应的测试和优化。

在这里插入图片描述

Java中Exception的使用方法

设计模式-策略模式

文章来源:https://blog.csdn.net/zhangzehai2234/article/details/135258463
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。