- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
面试官:“小伙子,线程池使用过吗,来聊一聊它吧!” 。
我:“好的,然后巴拉巴拉一顿输出之前看过的build哥线程池十八问...” 。
面试官满意的点了点头,紧接着问道:“那你知道如何优雅的关闭线程池吗?” 。
我:“知道知道,直接调用shutdownNow()方法就好了呀!” 。
面试官脸色一变,微怒道:“粗鲁!你给我滚出去!!!” 。
哈哈,上面的场景是build哥臆想出来的面试画面,我们现在步入正题,来看一看在线程池使用完成后如何优雅的关闭线程池.
在JDK 1.8 中,Java 并发工具包中 java.util.concurrent.ExecutorService 提供了 shutdown()、shutdownNow()这两种接口方法去关闭线程池,我们分别看一下.
shutdown() 。
public void shutdown() {
final ReentrantLock mainLock = this.mainLock; // ThreadPoolExecutor的主锁
mainLock.lock(); // 加锁以确保独占访问
try {
checkShutdownAccess(); // 检查是否有关闭的权限
advanceRunState(SHUTDOWN); // 将执行器的状态更新为SHUTDOWN
interruptIdleWorkers(); // 中断所有闲置的工作线程
onShutdown(); // ScheduledThreadPoolExecutor中的挂钩方法,可供子类重写以进行额外操作
} finally {
mainLock.unlock(); // 无论try块如何退出都要释放锁
}
tryTerminate(); // 如果条件允许,尝试终止执行器
}
在shutdown的源码中,会启动一次顺序关闭,在这次关闭中,执行器不再接受新任务,但会继续处理队列中的已存在任务,当所有任务都完成后,线程池中的线程会逐渐退出.
我们写一个小的demo来使用shutdown():
public class TestService{
public static void main(String[] args) {
//创建固定 3 个线程的线程池,测试使用,工作中推荐ThreadPoolExecutor
ExecutorService threadPool = Executors.newFixedThreadPool(3);
//向线程池提交 10 个任务
for (int i = 1; i <= 10; i++) {
final int index = i;
threadPool.submit(() -> {
System.out.println("正在执行任务 " + index);
//休眠 3 秒,模拟任务执行
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
//休眠 4 秒
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//关闭线程池
threadPool.shutdown();
}
}
在这段测试代码中,我们构造了一个包含固定3线程数的线程池,循环提交10个任务,每个任务休眠3秒,但主程序休眠4秒后,会掉用shutdown方法,理论上,在第二个时间循环中,线程池被停止,所以最多执行完6个任务,但从输出中,我们丝毫感受不好线程何时被停止了。 输出:
正在执行任务 1
正在执行任务 3
正在执行任务 2
正在执行任务 4
正在执行任务 5
正在执行任务 6
正在执行任务 7
正在执行任务 8
正在执行任务 9
正在执行任务 10
shutdownNow() 。
/**
* 尝试停止所有正在执行的任务,停止处理等待的任务,
* 并返回等待处理的任务列表。
*
* @return 从未开始执行的任务列表
*/
public List<Runnable> shutdownNow() {
List<Runnable> tasks; // 用于存储未执行的任务的列表
final ReentrantLock mainLock = this.mainLock; // ThreadPoolExecutor的主锁
mainLock.lock(); // 加锁以确保独占访问
try {
checkShutdownAccess(); // 检查是否有关闭的权限
advanceRunState(STOP); // 将执行器的状态更新为STOP
interruptWorkers(); // 中断所有工作线程
tasks = drainQueue(); // 清空队列并将结果放入任务列表中
} finally {
mainLock.unlock(); // 无论try块如何退出都要释放锁
}
tryTerminate(); // 如果条件允许,尝试终止执行器
return tasks; // 返回队列中未被执行的任务列表
}
与shutdown不同的是shutdownNow会尝试终止所有的正在执行的任务,清空队列,停止失败会抛出异常,并且返回未被执行的任务列表.
由于shutdownNow会有返回值,所以我们将上面的测试案例稍作改动后输出结果为:
这种会在控制台抛出异常的方式,同样也不优雅,所以我们继续往下看! 。
shutdown()+awaitTermination(long timeout, TimeUnit unit) 。
awaitTermination(long timeout, TimeUnit unit)是可以允许我们在调用shutdown方法后,再设置一个等待时间,如设置为5秒,则表示shutdown后5秒内线程池彻底终止,返回true,否则返回false,
这种方式里,我们将shutdown()结合awaitTermination(long timeout, TimeUnit unit)方法去使用,注意在调用 awaitTermination() 方法时,应该设置合理的超时时间,以避免程序长时间阻塞而导致性能问题,而且由于这个方法在超时后也会抛出异常,因此,我们在使用的时候要捕获并处理异常! 。
public class TestService{
public static void main(String[] args) {
//创建固定 3 个线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(3);
//向线程池提交 10 个任务
for (int i = 1; i <= 10; i++) {
final int index = i;
threadPool.submit(() -> {
System.out.println("正在执行任务 " + index);
//休眠 3 秒
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
//关闭线程池,设置等待超时时间 3 秒
System.out.println("设置线程池关闭,等待 3 秒...");
threadPool.shutdown();
try {
boolean isTermination = threadPool.awaitTermination(3, TimeUnit.SECONDS);
System.out.println(isTermination ? "线程池已停止" : "线程池未停止");
} catch (InterruptedException e) {
e.printStackTrace();
}
//再等待超时时间 20 秒
System.out.println("再等待 20 秒...");
try {
boolean isTermination = threadPool.awaitTermination(20, TimeUnit.SECONDS);
System.out.println(isTermination ? "线程池已停止" : "线程池仍未停止,请检查!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出:
设置线程池关闭,等待 3 秒...
正在执行任务 1
正在执行任务 2
正在执行任务 3
正在执行任务 4
正在执行任务 5
线程池未停止
再等待 20 秒...
正在执行任务 6
正在执行任务 7
正在执行任务 8
正在执行任务 9
正在执行任务 10
线程池已停止
从输出中我们可以看到,通过将两种方法结合使用,我们监控了整个线程池关闭的全流程,实现了优雅的关闭! 。
如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥! 。
如果您想与Build哥的关系更近一步,还可以关注“JavaBuild888”,在这里除了看到《Java成长计划》系列博文,还有提升工作效率的小笔记、读书心得、大厂面经、人生感悟等等,欢迎您的加入! 。
最后此篇关于面试官:说一说如何优雅的关闭线程池,我:shutdownNow,面试官:粗鲁!的文章就讲到这里了,如果你想了解更多关于面试官:说一说如何优雅的关闭线程池,我:shutdownNow,面试官:粗鲁!的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在开发一款扑翼应用程序。在出现此错误之前,读取和写入FireStore数据库没有任何问题,但随后突然出现错误(如下所示),并阻止我读取或写入数据库。我一直在寻找答案,但不幸的是,我找不到任何可以解
我正在使用ExecutorService连接任务如下: ExecutorService executor = Executors.newSingleThreadExecutor(); Future f
根据方法 shutdownNow (ExecutorService) 的文档 There are no guarantees beyond best-effort attempts to stop
我正在使用 Executors 作为线程池,并提交任务。 executorService.shutdownNow 是否可以关闭所有任务,即使其中一些任务可能在对数据库或 Socket 的 I/O 调用
我有一个预定的执行程序服务设置,例如 class Test { private final ScheduledExecutorService executor; public Test
我创建了一个 future 任务并将其提交给 Executor。在 run() 方法中,我创建了一个 placementPlanner 对象。此类中的方法调用其他类。但是,当我调用 executor.
我正在运行一个高度并发的 Java 程序。当许多线程向执行程序服务提交任务时,主线程会在某个时刻调用 ExecutorService.shutdownNow()。 执行此操作后,我希望: 执行者服务不
此代码在 future.get() 上永久阻塞。我本以为会出现 CancellationException 或 InterruptedException。谁能解释一下? ExecutorService
正在学习 Java 1.5 中引入的 ExecutorService 以下示例似乎违反了预期行为: public static void main(String[] args) throws Inte
我有一个使用 Executors 创建多个线程的主线程 ExecutorService executor = Executors.newFixedThreadPool(4); 每个线程都有可能运行数小
ExecutorService 有一个方法 List shutdownNow() 哪个 returns a list of the tasks that were awaiting execution
ScheduledExecutorService从 ExecutorService 继承了两个方法, shutdown()和 shutdownNow() .它们的区别: shutdown initia
我有一个表单的处理循环 while (true) { doWork(); Thread.sleep(SLEEP_INTERVAL); } 我想用它制作一个 Runnable,它可以很好
package util.concurrent; import java.util.concurrent.ExecutorService; import java.util.concurrent.Ex
写在开头 面试官:“小伙子,线程池使用过吗,来聊一聊它吧!” 我:“好的,然后巴拉巴拉一顿输出之前看过的build哥线程池十八问...” 面试官满意的点了点头,紧接着问道:“那你知道如何优雅
当其中一个已在运行的任务抛出异常时,我需要取消所有已安排但尚未运行的 CompletableFuture 任务。 尝试了以下示例,但大多数时候 main 方法不会退出(可能是由于某种类型的死锁)。 p
我正在实现一个传输服务器程序,该程序从客户端获取消息(通过控制台输入),然后将其转发到某种邮箱。 为了允许不同客户端同时接收多个消息,我首先创建了一个实现Runnable 接口(interface)的
在第一个进程从 invokeAny 方法提供一些输出后,我立即使用 shutdownNow 关闭进程。但在输出中,即使在调用 shutdownNow() 之后,我也可以看到进程仍在完成流程中并完成其工
执行调用的 ExecutorService.shutdownNow() 后,该类卡在 Future.get() 方法处。我不知道我犯了什么错误。 该类创建固定线程池,并在 5 秒后超时。如果连续发生
我目前有一个 ExecutorService,我想要以下内容: 不应接受任何新任务。 当前任务仍应继续执行。 应返回所有当前排队的任务。 我面临的问题是 shutdown() 不会返回任何未执行的已提
我是一名优秀的程序员,十分优秀!