• 如何优雅的终止线程 Java


    目录

    终止线程的方法

    打断sleep函数

    打断正常执行的线程

    两阶段终止模式

    错误的方法

    使用线程对象的 stop() 方法停止线程

    使用 System.exit(int) 方法停止线程

    正确的方法:使用 interrrupt


    终止线程的方法

    XXXThread.interrupt();

    在线程的 run函数中对该线程的中断标记进行判断,自行决定是否终止当前线程。

    以及在终止线程之前做一些工作。

    interrupt 这个方法并没有强制性地去中断线程任务,只是发送了一个信号给到线程自身,然后让线程自身去决定如何执行。

    正因为 interrupt 的灵活性会比较高,所以在 JDK 的线程池中,关于关闭部分的实现也是采用了 interrupt 去实现。

    打断sleep函数

    1. public class InterruptThread2 {
    2. static class TestInterruptedStop implements Runnable {
    3. @Override
    4. public void run() {
    5. synchronized (this) {
    6. //如果当前线程被中断,这里需要主动退出
    7. for (int i = 0; i < 100; i++) {
    8. try {
    9. Thread.sleep(1000);// sleep 被打断 抛出异常InterruptedException
    10. // 之后打断标记被清空
    11. } catch (InterruptedException e) {
    12. e.printStackTrace();
    13. System.out.println("sleep遇到了中断,程序即将终止");
    14. System.out.println("终止前的相关操作...");
    15. }
    16. System.out.println("running " + (i+1));
    17. }
    18. System.out.println("end");
    19. }
    20. }
    21. }
    22. public static void main(String[] args) throws InterruptedException {
    23. Thread testInterruptedStop = new Thread(new TestInterruptedStop());
    24. testInterruptedStop.start();
    25. Thread.sleep(2000);
    26. testInterruptedStop.interrupt();
    27. Thread.sleep(1000);
    28. System.out.println("testInterruptedStop is interrupted:" + testInterruptedStop.isInterrupted());
    29. }
    30. }

    打断正常执行的线程

    1. public class InterruptThread3 {
    2. static class TestInterruptedStop implements Runnable {
    3. @Override
    4. public void run() {
    5. synchronized (this) {
    6. int i = 1;
    7. while(!Thread.currentThread().isInterrupted()){
    8. System.out.println("running " + (i++));
    9. }
    10. if(Thread.currentThread().isInterrupted()){// 如果当前线程是打断状态
    11. System.out.println("遇到了中断,程序即将终止");
    12. System.out.println("执行终止前的相关操作...");
    13. }
    14. System.out.println("end");
    15. }
    16. }
    17. }
    18. public static void main(String[] args) throws InterruptedException {
    19. Thread testInterruptedStop = new Thread(new TestInterruptedStop());
    20. testInterruptedStop.start();
    21. Thread.sleep(2000);
    22. testInterruptedStop.interrupt();
    23. Thread.sleep(1000);
    24. System.out.println("testInterruptedStop is interrupted:" + testInterruptedStop.isInterrupted());
    25. }
    26. }

    两阶段终止模式

    在一个线程 T1 中如何 优雅 终止线程 T2 ?这里的【优雅】指的是给 T2 一个料理后事的机会。

    错误的方法

    使用线程对象的 stop() 方法停止线程


    stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁,其它线程将永远无法获取锁


    使用 System.exit(int) 方法停止线程


    目的仅是停止一个线程,但这种做法会让整个程序都停止

    正确的方法:使用 interrrupt

    如果被打断线程正处于 sleepwaitjoin这三种状态,则会导致被打断的线程抛出 InterruptedException,并清除打断标记,也就是置为 false。

    1. @Slf4j(topic = "c.TestTwoPhaseTermination")
    2. public class TestTwoPhaseTermination {
    3. public static void main(String[] args) throws InterruptedException {
    4. TPTInterrupt t = new TPTInterrupt();
    5. t.start();
    6. Thread.sleep(3500);
    7. log.debug("stop");
    8. t.stop();
    9. }
    10. }
    11. @Slf4j(topic = "c.TPTInterrupt")
    12. class TPTInterrupt {
    13. private Thread thread;
    14. public void start(){
    15. thread = new Thread(() -> {
    16. while(true) {
    17. Thread current = Thread.currentThread();
    18. if(current.isInterrupted()) {
    19. log.debug("料理后事");
    20. break;
    21. }
    22. try {
    23. Thread.sleep(1000);
    24. log.debug("将结果保存");
    25. } catch (InterruptedException e) {
    26. current.interrupt();// 打断标记被清空,需要重新打断设置打断标记为 true
    27. }
    28. }
    29. },"监控线程");
    30. thread.start();
    31. }
    32. public void stop() {
    33. thread.interrupt();
    34. }
    35. }

    sleep 的睡眠被打断会抛出异常,情况打断标记,因此在 catch 块中,需要重新设置打断标记。

     

  • 相关阅读:
    图扑软件助力企业数字化转型
    JAVASE语法零基础——Comparable接口、Comparator接口
    git 过滤不需要提交的目录和文件
    Android中eBPF使用原理以及 kprobe dmabuf_setup实例
    30% 的抽成太多了!马斯克:我想和苹果老板库克谈谈「苹果税」
    利用亚马逊 云服务器 EC2 和S3免费套餐搭建私人网盘
    基于ssm+jsp背单词系统的设计与实现
    GBase8s jdbc开启oracle兼容模式说明
    Vue中如何进行图像识别与人脸对比(如百度AI、腾讯AI)
    基于Python和lammps模拟聚合物交联过程
  • 原文地址:https://blog.csdn.net/weixin_40757930/article/details/128032436