线程池的关闭方式有几种,各自的区别是什么?

本文详细介绍了Java中ExecutorService的三种关闭方法:shutdown()用于平滑关闭,等待所有任务执行完毕;shutdownNow()强制关闭,尝试中断执行中的任务;awaitTermination()则用于阻塞等待任务结束或超时。选择合适的方法取决于具体的应用需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在Java中,线程池的关闭方式有三种:shutdown()、shutdownNow()和awaitTermination()。

  1.'shutdown()'方法:

  ·该方法会平滑地关闭线程池,不再接受新的任务提交。

  ·它会等待所有已提交的任务执行完毕,包括已经在等待队列中的任务。

  ·如果线程池已经关闭,则调用该方法没有任何效果。

ExecutorService executor = Executors.newFixedThreadPool(5);

// 执行任务...

executor.shutdown(); // 关闭线程池

// 等待线程池中的任务执行完毕
try {
    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
    // 处理中断异常
}

  2.'shutdownNow()'方法:

  ·该方法会强制关闭线程池,尝试中断正在执行的任务,并返回等待执行的任务列表。

  ·它会立即停止线程池的运行,不再处理等待队列中的任务。

  ·如果线程池已经关闭,则调用该方法没有任何效果。

ExecutorService executor = Executors.newFixedThreadPool(5);

// 执行任务...

List<Runnable> unprocessedTasks = executor.shutdownNow(); // 强制关闭线程池

// 处理未执行的任务
for (Runnable task : unprocessedTasks) {
    // 处理未执行的任务...
}

  3.'awaitTermination()'方法:

  ·该方法用于等待线程池中的任务执行完毕,或者在指定的时间内等待任务执行完毕。

  ·它会阻塞当前线程,直到满足以下条件之一:所有任务执行完毕、超过指定的等待时间、当前线程被中断。

  这些关闭方式可以根据具体需求选择合适的方法,shutdown()和awaitTermination()提供了一种平滑关闭线程池的方式,而shutdownNow()则提供了一种立即停止线程池的方式。

ExecutorService executor = Executors.newFixedThreadPool(5);

// 执行任务...

executor.shutdown(); // 关闭线程池

// 等待线程池中的任务执行完毕,最多等待1小时
try {
    if (!executor.awaitTermination(1, TimeUnit.HOURS)) {
        // 执行超时处理
    }
} catch (InterruptedException e) {
    // 处理中断异常
}

### 线程池拒绝策略的类型及各自的作用 Java 中 `ThreadPoolExecutor` 提供了几种内置的线程池拒绝策略,这些策略用于当线程池无法继续接收新任务时如何处理提交的任务。以下是常见的几种拒绝策略及其作用: #### 1. **AbortPolicy** 该策略会在任务被拒绝时抛出 `RejectedExecutionException` 异常[^2]。这种策略适用于希望程序能够感知到任务被拒绝的情况,并通过捕获异常来采取进一步措施。 ```java new ThreadPoolExecutor.AbortPolicy(); ``` #### 2. **CallerRunsPolicy** 此策略会由调用者线程(即提交任务的线程)执行被拒绝的任务[^1]。这种方式不会丢弃任务,也不会创建新的线程,而是让当前线程承担额外的工作负载。它通常用于短期过载情况下的恢复机制。 ```java new ThreadPoolExecutor.CallerRunsPolicy(); ``` #### 3. **DiscardPolicy** 该策略会静默地丢弃被拒绝的任务而不做任何处理[^1]。如果可以容忍某些任务偶尔失败,则可以选择此策略以减少资源消耗。 ```java new ThreadPoolExecutor.DiscardPolicy(); ``` #### 4. **DiscardOldestPolicy** 此策略会尝试丢弃最旧的一个未处理请求并重试提交当前任务[^1]。它的目的是为了腾出空间给最新到达的任务,从而避免长时间等待队列中的任务阻塞整个系统。 ```java new ThreadPoolExecutor.DiscardOldestPolicy(); ``` 除了以上四种标准策略外,还可以通过实现 `RejectedExecutionHandler` 接口来自定义拒绝策略[^1]。这允许开发者根据业务逻辑设计更加灵活的行为模式。 --- ### 示例代码展示不同拒绝策略的效果 下面是一个简单的例子展示了如何配置不同的拒绝策略以及它们的表现差异: ```java import java.util.concurrent.*; public class RejectionStrategyExample { public static void main(String[] args) throws InterruptedException { BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2); // 创建带有 CallerRunsPolicy 的线程池实例 ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, 2, 0L, TimeUnit.MILLISECONDS, queue, new ThreadPoolExecutor.CallerRunsPolicy() ); for (int i = 0; i < 5; i++) { int taskId = i; executor.submit(() -> System.out.println("Executing Task " + taskId)); } Thread.sleep(100); // 让主线程稍作延迟以便观察结果 executor.shutdownNow(); // 关闭线程池 } } ``` 在这个示例中,由于设置了较小的核心线程数和工作队列容量,超出部分的任务会被交给调用方运行。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值