目录

  • `Java` 中如何终止运行中的线程
    • 使用 `volatile` 修饰标志位终止
    • 使用 `stop()` 方法终止
    • 使用 `interrupt()` 方法终止
      • `interrupt()` 方法终止遇到 `sleep()` 或 `wait()`

Java 中如何终止运行中的线程

Java 中终止线程,通常意味着在线程处理任务完成之前停掉正在做的操作,也就是放弃当前的操作,在 Java 中有以下 3 种方法可以终止正在运行的线程

  • 使用 volatile 退出标志位,使线程正常退出,也就是当 run() 方法完成后线程中止
  • 使用 stop() 方法,已被弃用。原因是:stop() 是立即终止,会导致一些数据被到处理一部分就会被终止,而用户并不知道哪些数据被处理,哪些没有被处理,产生了不完整的“残疾”数据,不符合完整性,所以被废弃
  • 使用 interrupt() 方法中断线程。注意使用 interrupt() 方法中断正在运行中的线程只会修改中断状态位,可以通过 isInterrupted() 判断。如果使用 interrupt() 方法中断阻塞中的线程,那么就会抛出 InterruptedException 异常,可以通过 catch 捕获异常,然后进行处理后终止线程。有些情况,我们不能判断线程的状态,所以使用 interrupt() 方法时一定要慎重考虑

使用 volatile 修饰标志位终止

实现 Runnable 接口

public class MyRunable implements Runnable {// 定义退出标志,true会一直执行,false会退出循环// 使用volatile目的是保证可见性,一处修改了标志,处处都要去主存读取新的值public volatile boolean flag = true;@Overridepublic void run() {System.out.println("第" + Thread.currentThread().getName() + "个线程创建");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 退出标志生效位置,true会一直执行,false会退出循环while (flag) {System.out.println("线程正在执行中......");}System.out.println("第" + Thread.currentThread().getName() + "个线程终止");}
}

main() 方法中创建线程,在合适的时候,修改标志位,终止运行中的线程

public class TreadTest {public static void main(String[] arg) throws InterruptedException {MyRunable myRunable = new MyRunable();// 创建4个线程for (int i = 0; i < 4; i++) {Thread thread = new Thread(myRunable, i + "   ");thread.start();}// 主线程休眠Thread.sleep(2000);System.out.println("——————————————————————————");// 主线程来修改退出标志,使子线程终止myRunable.flag = false;}
}

运行结果

第1   个线程创建
第2   个线程创建
第0   个线程创建
第3   个线程创建
线程正在执行中......
线程正在执行中......
线程正在执行中......
线程正在执行中......
线程正在执行中......
线程正在执行中......
......................................省略
——————————————————————————
线程正在执行中......
第3   个线程终止
线程正在执行中......
第0   个线程终止
线程正在执行中......
第2   个线程终止
第1   个线程终止

使用 stop() 方法终止

通过查看 JDKAPI,我们会看到 java.lang.Thread 类型提供了一系列的方法如 start()、stop()、resume()、suspend()、destory() 等方法来管理线程。但是除了 start() 之外,其它几个方法都被声名为已过时 (deprecated)

虽然 stop() 方法确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且该方法已被弃用,最好不要使用它

  • 调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catchfinally 语句中的,并抛出 ThreadDeath 异常,因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题
  • 例如,存在一个对象 u 持有 IDNAME 两个字段,假如写入线程在写对象的过程中,只完成了对 ID 的赋值,但没来得及为 NAME 赋值,就被 stop() 导致锁被释放,那么当读取线程得到锁之后再去读取对象 uIDName 时,就会出现数据不一致的问题,如下图

使用 interrupt() 方法终止

需要明确的一点的是:interrupt() 方法并不像在 for 循环语句中使用 break 语句那样干脆,马上就停止循环。调用 interrupt() 方法仅仅是在当前线程中打一个停止的标记,并不是真的停止线程

也就是说,线程中断并不会立即终止线程,而是通知目标线程,有人希望你终止。至于目标线程收到通知后会如何处理,则完全由目标线程自行决定。这一点很重要,如果中断后,线程立即无条件退出,那么我们又会遇到 stop() 方法的老问题

public class InterruptThread extends Thread {public static void main(String[] args) {try {InterruptThread t = new InterruptThread();t.start();Thread.sleep(200);t.interrupt();} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic void run() {for (int i = 0; i <= 200000; i++) {System.out.println("i=" + i);}}
}

运行结果

......................................省略
i=199991
i=199992
i=199993
i=199994
i=199995
i=199996
i=199997
i=199998
i=199999
i=200000

从输出的结果我们会发现 interrupt() 方法并没有停止线程 t 中的处理逻辑,也就是说即使 t 线程被设置为了中断状态,但是这个中断并不会起作用,那么该如何停止线程呢

这就需要使用到另外两个与线程中断有关的方法了

public boolean Thread.isInterrupted() // 判断是否被中断public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态

这两个方法使得当前线程能够感知到是否被中断了(通过检查标志位)。所以如果希望线程 t 在中断后停止,就必须先判断是否被中断,并为它增加相应的中断处理代码

public class InterruptThread extends Thread {public static void main(String[] args) {try {InterruptThread t = new InterruptThread();t.start();Thread.sleep(200);t.interrupt();} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic void run() {for (int i = 0; i <= 200000; i++) {// 判断是否被中断if (Thread.currentThread().isInterrupted()) {// 处理中断逻辑break;}System.out.println("i=" + i);}}
}

运行结果

......................................省略
i=3177
i=3178
i=3179
i=3180
i=3181
i=3182
i=3183
i=3184
i=3185
i=3186

在上面这段代码中,我们增加了 Thread.isInterrupted() 来判断当前线程是否被中断了,如果是,则退出 for 循环,结束线程

interrupt() 方法终止遇到 sleep()wait()

这种方式看起来与之前介绍的使用 volatile 修饰标志位终止线程非常类似,但是在遇到 sleep() 或者 wait() 这样的操作,我们只能通过中断来处理了

public static native void sleep(long millis) throws InterruptedException
  • Thread.sleep() 方法会抛出一个 InterruptedException 异常,当线程被 sleep() 休眠时,如果被中断,就会抛出这个异常
  • Thread.sleep() 方法由于中断而抛出的异常,是会清除中断标记的

如何终止运行中的线程相关推荐

  1. c++ 如何给 “运行中“ 的线程传递数据;

    1:场景是有一个线程池,我需要将任务队列中发生读写事件的fd拿出来传递到线程池中 正常情况下创建线程时可以指定参数,比如这样 std::thread t(func,arg1,arg2,...) 但是我 ...

  2. 运行中的线程如何停止?

    停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作.停止一个线程可以用Thread.stop()方法,但最好不要用它.虽然它确实可以停止一个正在运行的线程,但是这个方法是不安 ...

  3. java 线程状态_浅析Java中的线程状态

    一.线程的5种状态 众所周知,Java的线程状态有5种,分别对应上图中五种不同颜色,下面对这5种状态及状态间的转化做相应的解释: 1. 初始化状态:新建一个线程对象 2. 可运行状态:其他线程调用了该 ...

  4. java异步线程数_spring异步service中处理线程数限制详解

    情况简介 spring项目,controller异步调用service的方法,产生大量并发. 具体业务: 前台同时传入大量待翻译的单词,后台业务接收单词,并调用百度翻译接口翻译接收单词并将翻译结果保存 ...

  5. python如何debug正在运行中的进程

    gunicorn+django开发的系统, 在排查卡住问题的时候,意外发现pstree -p pid(gunicorn的pid), 发现线程数量居高不下,只增不减.导致线程数大量增加.后面遇到卡顿的情 ...

  6. 如何查找历史线程阻塞原因_java并发编程-线程状态,线程阻塞方式,阻塞中的线程如何终止?...

    前面的例子通过volatile boolean来让任务终止,那么如果任务阻塞了? 如何终止它?本文来看下,参考think in java . 线程的状态 1.new:线程创建后的短暂状态,其分配系统资 ...

  7. 如何正确的终止正在运行的子线程

    最近开发一些东西,线程数非常之多,当用户输入Ctrl+C的情形下,默认的信号处理会把程序退出,这时有可能会有很多线程的资源没有得到很好的释放,造成了内存泄露等等诸如此类的问题,本文就是围绕着这么一个使 ...

  8. java程序中怎么保证多线程的运行安全_Java线程安全问答(草稿)

    1.什么是线程安全? 如果一个类在多线程执行中,在不考虑运行环境的调度干预,也不需要调用代码的协调同步,仍然保证正确地运行,那么这个类就是线程安全的 也就是说,多线程环境下,线程安全的类总是有正确的行 ...

  9. Java中一个线程只有六个状态。至于阻塞、可运行、挂起状态都是人们为了便于理解,自己加上去的。...

    java中,线程的状态使用一个枚举类型来描述的.这个枚举一共有6个值: NEW(新建).RUNNABLE(运行).BLOCKED(锁池).TIMED_WAITING(定时等待).WAITING(等待) ...

  10. 终止运行线程的注意事项

    终止运行线程 1. 线程函数返回. 2. 线程通过调用ExitThread函数"杀死"自己(避免使用). 3. 同一个进程或另一个进程中的线程调用TerminateThread函数 ...

最新文章

  1. 企业级 SpringBoot 教程 (十二)springboot集成apidoc
  2. 基于VHDL语言的数字秒表实现
  3. array sort - 4 : merge sort
  4. Dubbo + RestEasy 实现文件上传与下载
  5. python怎么用matplotlib_用Matplotlib在Python中绘制时间
  6. 一夜抢空880万!中国最狠印钞机,终于开始收割年轻人了
  7. wechat.php+获取昵称,微信后台代码,获取用户昵称
  8. 粒子群matlab工具箱,科学网—PSO粒子群优化算法Matlab工具箱 - 白途思的博文
  9. selenide UI自动化进阶二 pageObject实现页面管理
  10. Is It A Tree?(并查集)
  11. A Game with Traps—— 二分
  12. 基于Pytorch对凸函数采用SGD算法优化实例(附源码)
  13. 智鼎在线测评是测什么_人才测评工具和人才测评方法
  14. hi3519多sensor设置说明
  15. ELK之metricbeat
  16. linux下运行icem脚本,肿么安装linux版的icem
  17. Apache http设置反向代理和负载均衡
  18. 监听audio是否加载完毕
  19. 橙单微服务的权限部分
  20. 文本工具来查看、分析、统计,比较

热门文章

  1. 文件怎么更新_干货!Win10更新总失败?学会这三招搞定它
  2. 395.至少有K个重复字符的最长子串
  3. 388.文件的最长绝对路径
  4. 230.二叉搜索树中第K小的元素
  5. Cmdbuilding搭建简易流程及问题处理
  6. 【生信进阶练习1000days】day14-GenomicDataCommons(GDC)
  7. 【2011-2012 ACM-ICPC Northeastern European Regional Contest (NEERC 11) G】GCD Guessing Game【数论思维题】
  8. Model-free强化学习
  9. mysql卸载注意问题_mysql卸载注意事项
  10. mysql不安装在c_MySQL 的模块不能安装的解决方法