zoukankan      html  css  js  c++  java
  • Java线程中断的三种方法

    多线程编程中耗时线程是很常见的情况,有时候我们不得不在一个线程中去终止另一个耗时线程。JDK并不推荐直接停止比如this.stop(),这会导致一些异常,比如锁未释放程序一直死锁。JDK推荐使用一个线程去通知耗时线程该结束线程了,耗时线程做退出前的回收处理然后自己结束线程。

    自定义标志位终止

    使用volatile 修饰的变量isExit控制线程的退出,这种方法需要不断及时判断isExit的值

    public class FinishThreadLearn {
        public static void main(String[] args) throws InterruptedException {
            InterruptStopThread threadA = new InterruptStopThread("A");
            threadA.start();
            Thread.sleep(100);
            System.out.println("终止线程");
            threadA.isExit=true;
        }
    }
    
    class InterruptStopThread extends Thread {
        private String name;
        public volatile boolean isExit = false;
    
        public InterruptStopThread(String name) {
            this.name = name;
        }
    
        @Override
        public void run() {
            super.run();
            while (!isExit) {
                System.out.println("Thead:" + this.name + "正在运行");
            }
            System.out.println("线程结束运行");
        }
    }

    输出结果可以看到,线程并未立即终止,结束循环体后才最终结束线程。

    interrupt() 方式终止

    正常执行的代码

    public class FinishThreadLearn {
        public static void main(String[] args) throws InterruptedException {
            InterruptStopThread threadA = new InterruptStopThread("A");
            threadA.start();
            Thread.sleep(100);
            System.out.println("终止线程");
            threadA.interrupt();
        }
    }
    
    class InterruptStopThread extends Thread {
        private String name;
        public volatile boolean isExit = false;
    
        public InterruptStopThread(String name) {
            this.name = name;
        }
    
        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                System.out.println("Thead:" + this.name + "正在运行");
            }
            System.out.println("线程结束运行");
        }
    }

    执行结果

    处于阻塞休眠的代码

    这里有点不一样,interrupt()方式中断阻塞会把标志位清除并报出InterruptedException异常,所以要在catch的时候退出。

    public class FinishThreadLearn {
        public static void main(String[] args) throws InterruptedException {
            InterruptStopThread threadA = new InterruptStopThread("A");
            threadA.start();
            Thread.sleep(2000);
            System.out.println("终止线程");
            threadA.interrupt();
        }
    }
    
    class InterruptStopThread extends Thread {
        private String name;
        public volatile boolean isExit = false;
    
        public InterruptStopThread(String name) {
            this.name = name;
        }
    
        @Override
        public void run() {
            super.run();
            while (true) {
                System.out.println("Thead:" + this.name + "正在运行");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
            System.out.println("线程结束运行");
        }
    }

    执行结果

    stop()强行停止

    public class FinishThreadLearn {
        public static void main(String[] args) throws InterruptedException {
            InterruptStopThread threadA = new InterruptStopThread("A");
            threadA.start();
            Thread.sleep(100);
            System.out.println("终止线程");
            threadA.stop();
        }
    }
    
    class InterruptStopThread extends Thread {
        private String name;
        public volatile boolean isExit = false;
    
        public InterruptStopThread(String name) {
            this.name = name;
        }
    
        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                System.out.println("Thead:" + this.name + "正在运行");
            }
            System.out.println("线程结束运行");
        }
    }

    从执行结果可以看到,run方法并未完全执行完就结束了,所以这种方法不推荐使用

    源码分析

    Thread源码中使用了一个volatile修饰的标志位控制终止信号

    public class Thread implements Runnable {
        ...
        /* Interrupt state of the thread - read/written directly by JVM */
        private volatile boolean interrupted;
        ...
    }

    interrupt方法会使标志位变为true

    判断线程是否终止JDK提供了两种方式

    Thread.interrupted():测试当前线程是否已经中断
    this.isInterrupted():测试线程是否已经中断

     this.isInterrupted()

    调用isInterrupted会返回该标志位

     

     Thread.interrupted()

     调用interrupted会返回该标志位,如果为ture会将标志位清空,且这个方法为静态方法

  • 相关阅读:
    GridView合并表头多重表头
    C# 导出Excel或Word
    GridView的分页功能?
    如何在GridView中判断Radio被选中?
    GridView無數據時,顯示表頭
    Oracle replace函数使用
    获取数据后导出Excel
    Oracel用rownum实现真分页
    转载C#泛型集合—Dictionary<K,V>使用技巧
    临时向表插入有自增的字段的记录
  • 原文地址:https://www.cnblogs.com/billshen/p/13292898.html
Copyright © 2011-2022 走看看