线程池提供了一种高效的线程复用机制,线程池中的线程执行完任务后,并不会立即被销毁,而是会继续保持活动状态,等待下一个任务的到来。
在 Java 中,线程池管理着多个线程的创建、执行和销毁。线程池中的线程通常在完成任务后等待新的任务或被销毁**。线程池本身并不直接停止线程**,而是通过任务的完成和线程池的关闭来管理线程生命周期。
在 Java 中,线程池本身不会自动停止,必须通过调用线程池的关闭方法来停止线程池中的线程。常见的线程池停止方法有:
线程池的停止主要通过 ExecutorService
接口提供的方法来控制:
使用 ExecutorService
类时,经常用到 shutdown()
、shutdownNow()
、awaitTermination()
3个方法.
shutdown():停止接收新任务,原来的任务继续执行
shutdown()
方法用于平滑地关闭线程池。调用此方法后,线程池会停止接受新任务,但会继续执行当前队列中等待的任务,直到所有任务执行完毕。
特点:
shutdown()
后,线程池不再接受新的任务。ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(() -> {
// 执行任务
});
// 请求关闭线程池,不会立即终止线程池中的线程
executorService.shutdown();
shutdownNow()
:停止接收新任务,原来的任务停止执行
shutdownNow()
方法用于强制关闭线程池。它会尝试停止所有正在执行的任务,并返回尚未执行的任务列表。这个方法会尝试中断线程池中的所有线程,并停止执行新的任务。已提交的任务不会再被接收.
特点:
跟 shutdown() 一样,先停止接收新submit的任务;
调用 shutdownNow()
后,线程池会尝试停止正在执行的任务,并清空任务队列。
如果线程正在执行任务,它们会被中断。
(注意:它并不会强制中止正在运行的任务,而是试图通过中断来停止任务。)
尝试将正在执行的任务interrupt中断;
任务队列中的任务会被返回,可以手动决定是否继续执行这些任务。
返回未执行的任务列表;
说明:它试图终止线程的方法是通过调用 Thread.interrupt() 方法来实现的,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt() 方法是无法中断当前的线程的。所以,shutdownNow() 并不代表线程池就一定立即就能退出,它也可能必须要等待所有正在执行的任务都执行完成了才能退出。但是大多数时候是能立即退出的。
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(() -> {
// 执行任务
});
List<Runnable> remainingTasks = executorService.shutdownNow(); // 请求强制关闭线程池,返回未执行的任务列
awaitTermination()
方法不是用于停止线程池的,而是用于等待线程池中的任务完成。在调用 shutdown()
或 shutdownNow()
后,可以调用此方法来阻塞当前线程,直到线程池中的任务完成或超时。
当前线程阻塞,直到:
然后会监测 ExecutorService 是否已经关闭,返回true(shutdown请求后所有任务执行完毕)或false(已超时)
特点:
shutdown()
或 shutdownNow()
使用。ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(() -> {
// 执行任务
});
executorService.shutdown(); // 请求关闭线程池
try {
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
executorService.shutdownNow(); // 如果超时,则强制关闭线程池
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
shutdown()
只是关闭了提交通道,用submit()是无效的;而内部该怎么跑还是怎么跑,跑完再停。
shutdownNow()
能立即停止线程池,正在跑的和正在等待的任务都停下了。
shutdown()
后,不能再提交新的任务进去;但是 awaitTermination()
后,可以继续提交。
awaitTermination()
是阻塞的,返回结果是线程池是否已停止(true/false);shutdown()
不阻塞。
线程池中的线程停止时,通常是通过 中断 线程来实现的。线程池中的线程在执行任务时会被要求定期检查是否被中断,若检测到中断信号(例如通过 Thread.interrupted()
或 isInterrupted()
),线程会终止正在执行的任务并退出。
**Thread.interrupt()**
:该方法会中断线程,并设置线程的中断标志。**Thread.isInterrupted()**
:判断线程是否被中断。**Thread.interrupted()**
:清除当前线程的中断状态并返回中断状态。Runnable task = () -> {
try {
while (!Thread.currentThread().isInterrupted()) {
// 执行任务
// 如果需要退出,可以抛出 InterruptedException 或检查中断状态
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
}
};
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(task);
// 关闭线程池时中断线程
executorService.shutdownNow(); // 会尝试中断线程池中的所有线程
如果任务本身执行较为复杂且需要响应停止命令,可以在任务中添加适当的逻辑来响应线程池的停止请求。例如,在任务执行时,可以定期检查 Thread.currentThread().isInterrupted()
或者通过捕获 InterruptedException
来判断线程是否需要停止。
InterruptedException
来停止正在执行的任务。Runnable task = () -> {
try {
for (int i = 0; i < 100; i++) {
if (Thread.currentThread().isInterrupted()) {
break; // 响应中断,退出任务
}
// 执行任务
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
}
};
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(task);
// 停止线程池
executorService.shutdownNow(); // 会中断正在执行的线程
shutdown()
或 shutdownNow()
后,线程池会正常终止执行当前的任务,但是它们并不会立即停止线程池中的所有线程。如果任务尚未完成,线程池会继续处理剩余的任务,直到所有任务执行完毕或被中断。shutdownNow()
请求线程池停止时,线程池会尝试中断所有线程,但并不保证线程立即停止。线程的停止依赖于任务本身是否能够响应中断,只有在任务响应中断时,线程才会结束执行。shutdown()
或 shutdownNow()
,线程池会停止接受新任务。如果想要提交新任务,必须创建新的线程池实例。在 Java 中,线程池的停止可以通过 shutdown()
或 shutdownNow()
方法来实现:
**shutdown()**
:平滑关闭线程池,不会立即中止任务,会等待现有任务执行完毕。**shutdownNow()**
:强制关闭线程池,会尝试中断正在执行的任务,并清空任务队列。**awaitTermination()**
:等待线程池中的所有任务完成,或者超时。1、优雅的关闭,用 shutdown()
2、想立马关闭,并得到未执行任务列表,用shutdownNow()
3、优雅的关闭,并允许关闭声明后新任务能提交,用 awaitTermination()
4、关闭功能 【从强到弱】 依次是:shuntdownNow() > shutdown() > awaitTermination()
线程池中的线程停止依赖于任务的中断机制,线程池会通过中断线程来请求停止正在执行的任务,因此在任务执行过程中,需要处理好中断逻辑,确保线程能够响应停止请求。
在 Java 中,最初设计了 Thread.stop() 方法来强制停止线程,但该方法已被废弃,因为它会导致线程在中途停止时保持不一致的状态,容易引发资源泄露或不完整的操作。
aitTermination()
线程池中的线程停止依赖于任务的中断机制,线程池会通过中断线程来请求停止正在执行的任务,因此在任务执行过程中,需要处理好中断逻辑,确保线程能够响应停止请求。
在 Java 中,最初设计了 Thread.stop() 方法来强制停止线程,但该方法已被废弃,因为它会导致线程在中途停止时保持不一致的状态,容易引发资源泄露或不完整的操作。