浅谈Java关闭线程池shutdown和shutdownNow的区别

  

浅谈Java关闭线程池shutdown和shutdownNow的区别

引言

线程池是Java中常用的多线程技术,它能够管理多个线程,统一分配调度线程的执行。对于线程池在使用完成后的关闭,Java提供了两种方法:shutdown()shutdownNow()。本文将分别介绍这两种方法的用法和区别。

前置概念

在介绍两种关闭方法之前,我们需要先了解一些前置概念。

ExecutorService

在Java中,ExecutorService是用于管理线程池的接口,它可以提交任务到线程池并执行。我们可以通过如下代码获得一个ExecutorService实例:

ExecutorService executorService = Executors.newFixedThreadPool(10);

上面这行代码创建了10个线程的线程池,可以执行10个任务。

Future

Future是Java中处理异步结果的接口,它代表异步计算的结果。我们可以通过调用Future.get()方法获得异步计算的结果,在Future.get()方法调用之前,当前线程将会一直被阻塞。

Callable和Runnable

Callable和Runnable都是Java中的接口,它们都可以作为线程池执行的任务。

Runnable代表一个无返回值的任务,可以通过实现Runnable接口并实现run()方法来表示一个任务。

Callable代表有返回值的任务,与Runnable不同,它的call()方法会返回一个结果。

shutdown()方法

shutdown()方法是关闭线程池的一种方式。该方法将线程池的状态设为SHUTDOWN,并尝试让线程池中所有的任务执行完成。

方法签名

void shutdown()

示例说明

下面是一个使用shutdown()方法关闭线程池的示例:

ExecutorService executorService = Executors.newFixedThreadPool(5);

for (int i = 0; i < 10; i++) {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println("Thread ID: " + Thread.currentThread().getId() 
                                + " is running");
        }
    });
}

executorService.shutdown();

try {
    executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
    e.printStackTrace();
}

System.out.println("All threads have finished");

上述示例代码中,使用了ExecutorService提交了10个任务到线程池中,然后调用shutdown()方法关闭了线程池。最后使用awaitTermination()方法等待线程池的任务执行完毕。

shutdownNow()方法

shutdownNow()方法也是关闭线程池的一种方式。该方法将线程池的状态设为STOP,并尝试中断所有运行中的线程,来停止当前正在执行中的任务。

方法签名

List<Runnable> shutdownNow()

示例说明

下面是一个使用shutdownNow()方法关闭线程池的示例:

ExecutorService executorService = Executors.newFixedThreadPool(5);

for (int i = 0; i < 10; i++) {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread ID: " + Thread.currentThread().getId() 
                                + " is running");
        }
    });
}

List<Runnable> notStartedTasks = executorService.shutdownNow();

System.out.println("Number of not started tasks: " + notStartedTasks.size());

上述示例代码中,使用了ExecutorService提交了10个任务到线程池中,这些任务都会延迟1秒后打印线程ID。之后调用了shutdownNow()方法关闭了线程池,收集了所有未被启动的任务。最后输出了未被启动的任务数量。

shutdown()和shutdownNow()方法的区别

两种关闭线程池的方法有以下区别:

  • shutdown()方法会尝试让线程池中所有的任务执行完成,而shutdownNow()方法则会立即停止所有正在执行的任务。
  • 对于shutdown()方法,如果线程池提交了一些任务并且正在执行中,调用shutdown()方法后会等待这些任务执行完再关闭线程池;而对于shutdownNow()方法,会将正在执行的任务中断并关闭线程池。

总结

本文通过讲解ExecutorService、Future、Callable、Runnable等Java中的相关概念,介绍了Java中关闭线程池的两种方式:shutdown()和shutdownNow()。实际使用时,需要根据需求来选择正确的关闭方式以确保程序能够正确运行。

相关文章