Java ThreadPoolExecutorg关闭线程池(附带实例)
在实际应用中,线程池的关闭是一项非常重要的工作,在程序中优雅且安全地关闭一个线程池的目的是确保以下几点:
在 Java 开发中,ThreadPoolExecutor 提供了下面两个关闭方法:
一般来说,shutdown() 方法的关闭方式更加温和和优雅。如果需要立即关闭线程池且不关心正在执行的任务,可以使用 shutdownNow(),但通常不推荐,因为它可能导致执行中的任务被中断。
下面的示例为我们展示了如何优雅且安全地关闭一个线程池:
程序中设置的等待时间为 Long.MAX_VALUE,基本上会无限期地等待,除非线程被中断。如果需要在指定的时间内关闭线程池,可以指定具体的时长参数。
- 所有已经提交的任务都得到执行;
- 没有新的任务被提交到线程池;
- 线程池在完成所有任务后能够正常关闭;
- 保证应用程序平滑、安全、有序地关闭。
在 Java 开发中,ThreadPoolExecutor 提供了下面两个关闭方法:
- shutdown() 方法:将启动线程池有序地关闭线程,但它允许已提交的任务继续执行,不再接收新任务;
- shutdownNow() 方法:将尝试立即停止所有正在执行的任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
一般来说,shutdown() 方法的关闭方式更加温和和优雅。如果需要立即关闭线程池且不关心正在执行的任务,可以使用 shutdownNow(),但通常不推荐,因为它可能导致执行中的任务被中断。
下面的示例为我们展示了如何优雅且安全地关闭一个线程池:
import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ShutDownThreadPoolExample { public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(5); // 模拟提交10个任务到线程池 for (int i = 0; i < 10; i++) { executorService.submit(() -> { try { // 假设每个任务需要1s来执行 TimeUnit.SECONDS.sleep(1); System.out.println("任务执行: " + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } }); } // 启动线程池有序地关闭线程,不再接收新任务,但已提交的任务将继续执行直到完成 executorService.shutdown(); // 可以无限期地等待所有任务完成 // 将等待时间设置为最大值 executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); System.out.println("所有任务已完成,线程池已关闭"); } }在上述代码中,我们首先使用 shutdown() 方法发起了关闭,然后通过 awaitTermination() 方法等待所有已提交的任务完成。awaitTermination() 方法会阻塞当前线程,直到所有任务在关闭请求后完成执行,或者发生超时,或者当前线程被中断。
程序中设置的等待时间为 Long.MAX_VALUE,基本上会无限期地等待,除非线程被中断。如果需要在指定的时间内关闭线程池,可以指定具体的时长参数。