线程中断机制

如何中断一个线程?

首先一个线程不应该由其他线程来强制中断或者停止,而是应该由线程自己自行停止。所以我们看到线程的stop()、resume()、suspend()等方法已经被标记为过时了。

其次在java中没有办法立即停止一个线程,然而停止线程显得尤为重要,比如取消一个耗时的操作。因此java提供了一种用于停止线程的协商机制 - 中断,也就是中断标识协商机制。如果你要中断一个线程,你需要手动调用该线程的interrupt方法,改方法仅仅将该线程对象的中断标设置成true,接着程序员需要自己写代码不断的检测当前线程的标识位。

中断线程三个相关方法

interrupt()

该方法是一个实例方法,仅仅是设置线程的中断标识状态为true,发起一个协商而不会立即停止改线程。

interrupted()

该方法是一个静态方法,判断线程是否被中断并清除当前线程中断状态。该方法干了两个事情:

  1. 返回当前线程中断状态,测试当前线程是否已经被中断
  2. 将当前线程的中断状态重新设置成false,清除线程的中断状态

isInterrupted()

该方法是一个实例方法,判断当前线程是否被中断

中断一个线程的正确姿势

volatile关键字修饰的变量

java 复制代码
    static volatile boolean volatileStop = false;

    public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                if (volatileStop) {
                    System.out.println(Thread.currentThread().getName() + ",跳出当前循环");
                    break;
                }
                System.out.println(Thread.currentThread().getName() + ",hell volatile");
            }

        }, "A").start();

        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            volatileStop = true;
        }, "B").start();
    }

通过AtomicBoolean

java 复制代码
   static AtomicBoolean atomicStop = new AtomicBoolean();

    public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                if (atomicStop.get()) {
                    System.out.println(Thread.currentThread().getName() + ",atomicStop被设置成true,跳出当前循环");
                    break;
                }
                System.out.println(Thread.currentThread().getName() + ",hell AtomicBoolean");
            }

        }, "A").start();

        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            atomicStop.set(true);
        }, "B").start();
    }

通过Thread自带的api:insterrupt()方法和isInterrupted()方法

在需要中断的线程中不断监听中断状态,一旦发生中断就执行相应的中断处理业务逻辑stop线程。

java 复制代码
public static void main(String[] args) {
        Thread a= new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + ",isInterrupted 被设置成true,跳出当前循环");
                    break;
                }
                System.out.println(Thread.currentThread().getName() + ",hell interrupt api");
            }

        }, "A");
        a.start();

        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            a.interrupt();
        }, "B").start();
    }

总结

当对一个线程调用interrupt()方法时:

  1. 如果线程处于正常活动状态,那么会将该线程的中断标志位设置为true,仅此而已。被设置中断标识的线程将继续正常运行,不受影响。所以interrupt()方法并不能真正的中断线程,需要被调用方的线程自己配合好才行。
  2. 如果线程处于被阻塞状态(例如:sleep、wait、join等),在别的线程中调用interrupt方法,那么该线程将立即退出阻塞状态,并抛出一个InterruptedException异常,且会清除线程的中断状态。
  3. 如果线程已经中断、不活动将不会有任何影响。
相关推荐
KGback1 年前
论文解析——Implementing Precise Interrupts in Pipelined Processors
pipeline·cpu·interrupt