0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何正确关闭线程池

Android编程精选 来源:CSDN博客 作者:不懂的浪漫 2021-09-29 14:41 次阅读

前言本章分为两个议题

如何正确关闭线程池

shutdown 和 shutdownNow 的区别

项目环境jdk 1.8

github 地址:https://github.com/huajiexiewenfeng/java-concurrent

本章模块:threadpool

1.线程池示例

public class ShutDownThreadPoolDemo {

private ExecutorService service = Executors.newFixedThreadPool(10);

public static void main(String[] args) {

new ShutDownThreadPoolDemo().executeTask();

}

public void executeTask() {

for (int i = 0; i 《 100; i++) {

service.submit(() -》 {

System.out.println(Thread.currentThread().getName() + “-》执行”);

});

}

}

}

执行结果

pool-1-thread-2-》执行

pool-1-thread-3-》执行

pool-1-thread-1-》执行

pool-1-thread-4-》执行

pool-1-thread-5-》执行

pool-1-thread-6-》执行

。..

执行完成之后,主线程会一直阻塞,那么如何关闭线程池呢?本章介绍 5 种在 ThreadPoolExecutor 中涉及关闭线程池的方法,如下所示

void shutdown

boolean isShutdown

boolean isTerminated

boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException

List《Runnable》 shutdownNow

2.shutdown

第一种方法叫作 shutdown(),它可以安全地关闭一个线程池,调用 shutdown() 方法之后线程池并不是立刻就被关闭,因为这时线程池中可能还有很多任务正在被执行,或是任务队列中有大量正在等待被执行的任务,调用 shutdown() 方法后线程池会在执行完正在执行的任务和队列中等待的任务后才彻底关闭。

调用 shutdown() 方法后如果还有新的任务被提交,线程池则会根据拒绝策略直接拒绝后续新提交的任务。学习资料:Java进阶视频资源

这段源码位置(jdk 1.8 版本)

java.util.concurrent.ThreadPoolExecutor#execute

public void execute(Runnable command) {

if (command == null)

throw new NullPointerException();

int c = ctl.get();

// 线程池中的线程比核心线程数少

if (workerCountOf(c) 《 corePoolSize) {

// 新建一个核心线程执行任务

if (addWorker(command, true))

return;

c = ctl.get();

}

// 核心线程已满,但是任务队列未满,添加到队列中

if (isRunning(c) && workQueue.offer(command)) {

int recheck = ctl.get();

// 任务成功添加到队列以后,再次检查是否需要添加新的线程,因为已存在的线程可能被销毁了

if (! isRunning(recheck) && remove(command))

// 如果线程池处于非运行状态,并且把当前的任务从任务队列中移除成功,则拒绝该任务

reject(command);

else if (workerCountOf(recheck) == 0)

// 如果之前的线程已经被销毁完,新建一个非核心线程

addWorker(null, false);

}

// 核心线程池已满,队列已满,尝试创建一个非核心新的线程

else if (!addWorker(command, false))

// 如果创建新线程失败,说明线程池关闭或者线程池满了,拒绝任务

reject(command);

}

1373 行 if (! isRunning(recheck) && remove(command))如果线程池被关闭,将当前的任务从任务队列中移除成功,并拒绝该任务

1378 行 else if (!addWorker(command, false))如果创建新线程失败,说明线程池关闭或者线程池满了,拒绝任务。

3.isShutdown

第二个方法叫作 isShutdown(),它可以返回 true 或者 false 来判断线程池是否已经开始了关闭工作,也就是是否执行了 shutdown 或者 shutdownNow 方法。

这里需要注意,如果调用 isShutdown() 方法的返回的结果为 true 并不代表线程池此时已经彻底关闭了,这仅仅代表线程池开始了关闭的流程,也就是说,此时可能线程池中依然有线程在执行任务,队列里也可能有等待被执行的任务。

4.isTerminated

第三种方法叫作 isTerminated(),这个方法可以检测线程池是否真正“终结”了,这不仅代表线程池已关闭,同时代表线程池中的所有任务都已经都执行完毕了。

比如我们上面提到的情况,如果此时已经调用了 shutdown 方法,但是还有任务没有执行完,那么此时调用 isShutdown 方法返回的是 true,而 isTerminated 方法则会返回 false。

直到所有任务都执行完毕了,调用 isTerminated() 方法才会返回 true,这表示线程池已关闭并且线程池内部是空的,所有剩余的任务都执行完毕了。

学习资料:Java进阶视频资源

5.awaitTermination

第四个方法叫作 awaitTermination(),它本身并不是用来关闭线程池的,而是主要用来判断线程池状态的。

比如我们给 awaitTermination 方法传入的参数是 10 秒,那么它就会陷入 10 秒钟的等待,直到发生以下三种情况之一:

等待期间(包括进入等待状态之前)线程池已关闭并且所有已提交的任务(包括正在执行的和队列中等待的)都执行完毕,相当于线程池已经“终结”了,方法便会返回 true

等待超时时间到后,第一种线程池“终结”的情况始终未发生,方法返回 false

等待期间线程被中断,方法会抛出 InterruptedException 异常

调用 awaitTermination 方法后当前线程会尝试等待一段指定的时间,如果在等待时间内,线程池已关闭并且内部的任务都执行完毕了,也就是说线程池真正“终结”了,那么方法就返回 true,否则超时返回 fasle。

6.shutdownNow

最后一个方法是 shutdownNow(),它和 shutdown() 的区别就是多了一个 Now,表示立刻关闭的意思,不推荐使用这一种方式关闭线程池。

在执行 shutdownNow 方法之后,首先会给所有线程池中的线程发送 interrupt 中断信号,尝试中断这些任务的执行,然后会将任务队列中正在等待的所有任务转移到一个 List 中并返回,我们可以根据返回的任务 List 来进行一些补救的操作,例如记录在案并在后期重试。

shutdownNow 源码如下:

public List《Runnable》 shutdownNow() {

List《Runnable》 tasks;

final ReentrantLock mainLock = this.mainLock;

mainLock.lock();

try {

checkShutdownAccess();

advanceRunState(STOP);

interruptWorkers();

tasks = drainQueue();

} finally {

mainLock.unlock();

}

tryTerminate();

return tasks;

}

interruptWorkers

让每一个已经启动的线程都中断,这样线程就可以在执行任务期间检测到中断信号并进行相应的处理,提前结束任务

7.shutdown 和 shutdownNow 的区别?

shutdown 会等待线程池中的任务执行完成之后关闭线程池,而 shutdownNow 会给所有线程发送中断信号,中断任务执行,然后关闭线程池

shutdown 没有返回值,而 shutdownNow 会返回关闭前任务队列中未执行的任务集合(List)

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 模块
    +关注

    关注

    7

    文章

    2722

    浏览量

    47574
  • 多线程
    +关注

    关注

    0

    文章

    278

    浏览量

    20022

原文标题:正确关闭线程池:shutdown 和 shutdownNow 的区别

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Python中多线程和多进程的区别

    Python作为一种高级编程语言,提供了多种并发编程的方式,其中多线程与多进程是最常见的两种方式之一。在本文中,我们将探讨Python中多线程与多进程的概念、区别以及如何使用线程与进
    的头像 发表于 10-23 11:48 424次阅读
    Python中多<b class='flag-5'>线程</b>和多进程的区别

    智能水表怎么安装是正确的?

    正确安装智能水表不仅能确保其正常工作,还能延长使用寿命,提高测量精度。下面我们将详细介绍智能水表的正确安装步骤和注意事项,帮助您顺利完成安装。1.准备工具和材料-工具:扳手、管钳、生料带、螺丝刀等
    的头像 发表于 09-21 15:44 519次阅读
    智能水表怎么安装是<b class='flag-5'>正确</b>的?

    买药秒送 JADE动态线程实践及原理浅析

    一、背景及JADE介绍 买药秒送是健康即时零售业务新的核心流量场域,面对京东首页高流量曝光,我们对频道页整个技术架构方案进行升级,保障接口高性能、系统高可用。 动态线程是买药频道应用的技术之一
    的头像 发表于 09-04 11:11 864次阅读
    买药秒送 JADE动态<b class='flag-5'>线程</b><b class='flag-5'>池</b>实践及原理浅析

    CPU线程和程序线程的区别

    CPU的线程与程序的线程在概念、作用、实现方式以及性能影响等方面存在显著差异。以下是对两者区别的详细阐述,旨在深入探讨这一技术话题。
    的头像 发表于 09-02 11:18 1084次阅读

    基于OpenHarmony标准系统的C++公共基础类库案例:ThreadPoll

    ) { // 等待关闭所有的线程,会等待线程程序全部结束才返回 cout << \"stop thread: start\" <<
    发表于 08-12 11:42

    探索虚拟线程:原理与实现

    虚拟线程的引入与优势 在Loom项目之前,Java虚拟机(JVM)中的线程是通过java.lang.Thread类型来实现的,这些线程被称为平台线程。 然而,平台
    的头像 发表于 06-24 11:35 321次阅读
    探索虚拟<b class='flag-5'>线程</b>:原理与实现

    鸿蒙开发:【线程模型】

    管理其他线程的ArkTS引擎实例,例如使用TaskPool(任务)创建任务或取消任务、启动和终止Worker线程
    的头像 发表于 06-13 16:38 428次阅读
    鸿蒙开发:【<b class='flag-5'>线程</b>模型】

    动态线程思想学习及实践

    相关文档 美团线程实践:https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html 线程思想解
    的头像 发表于 06-13 15:43 1205次阅读
    动态<b class='flag-5'>线程</b><b class='flag-5'>池</b>思想学习及实践

    OpenHarmony语言基础类库【@ohos.taskpool(启动任务)】

    任务(taskpool)作用是为应用程序提供一个多线程的运行环境,降低整体资源的消耗、提高系统的整体性能,且您无需关心线程实例的生命周期。您可以使用任务API创建后台任务(Task
    的头像 发表于 04-24 17:45 365次阅读
    OpenHarmony语言基础类库【@ohos.taskpool(启动任务<b class='flag-5'>池</b>)】

    鸿蒙APP开发:【ArkTS类库多线程】TaskPool和Worker的对比

    TaskPool(任务)和Worker的作用是为应用程序提供一个多线程的运行环境,用于处理耗时的计算任务或其他密集型任务。可以有效地避免这些任务阻塞主线程,从而最大化系统的利用率,降低整体资源消耗,并提高系统的整体性能。
    的头像 发表于 03-26 22:09 670次阅读
    鸿蒙APP开发:【ArkTS类库多<b class='flag-5'>线程</b>】TaskPool和Worker的对比

    java实现多线程的几种方式

    了多种实现多线程的方式,本文将详细介绍以下几种方式: 1.继承Thread类 2.实现Runnable接口 3.Callable和Future 4.线程 5.Java 8中
    的头像 发表于 03-14 16:55 755次阅读

    python中5种线程锁盘点

    线程安全是多线程或多进程编程中的一个概念,在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且
    发表于 03-07 11:08 1623次阅读
    python中5种<b class='flag-5'>线程</b>锁盘点

    使用ATOM和DTM关闭所有开关的正确方法是什么?

    = 1、SL0_x = 0、SL1_x = 0。但是,我不确定这是否是完成任务的适当方法。 在不依赖外部触发器的情况下,通过软件关闭(设置为低电平)所有输出的\"正确\" 方法是什么?
    发表于 03-04 06:11

    什么是动态线程?动态线程的简单实现思路

    因此,动态可监控线程一种针对以上痛点开发的线程管理工具。主要可实现功能有:提供对 Spring 应用内线程
    的头像 发表于 02-28 10:42 659次阅读

    .NET8性能优化之线程

    目前来说,没有确切的证据证明哪个线程好用,或者效率更高。但是开发者可以使用上面的选项来进行自己的选择,有一个测试就是在Windows线程在比较大的机器上的IO扩展性不太好。如果你的
    的头像 发表于 01-22 14:50 1181次阅读