单个 Thread.interrupt() 中断不止一次

Single Thread.interrupt() interrupts more than once

我创建了 MyTask,它在 run() 中有 3 件事要做。我尝试 interrupt() 持有 MyTask 实例的线程。不幸的是,一旦它被打断,它就会结束,并且只有字符串 First task 会打印在控制台上。

public class MyTask implements Runnable {
    private volatile Thread thread;

    @Override
    public void run() {
        while (!thread.isInterrupted()) {
            System.out.println("First task");
        }
        while (!thread.isInterrupted()) {
            System.out.println("Second task");
        }
        while (!thread.isInterrupted()) {
            System.out.println("Third task");
        }
    }

    public Thread start(){
        thread = new Thread(this);
        thread.start();
        return thread;
    }


    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyTask().start();
        Thread.sleep(1000);
        t.interrupt();
        Thread.sleep(1000);
        t.interrupt();
        Thread.sleep(1000);
        t.interrupt();
    }

}

如果我在 run() 中添加 Thread.sleep(10) 它开始 正常工作 并打印 First taskSecond task 和终于在控制台上 Third task

问题是:为什么 Thread.interrupts() 只有添加 sleep() 才能正常工作?

public class MyTask implements Runnable {
    private volatile Thread thread;

    @Override
    public void run() {
        while (!thread.isInterrupted()) {
            System.out.println("First task");
        }
        try {
            Thread.sleep(10);
        } catch (Exception e) {
        }
        while (!thread.isInterrupted()) {
            System.out.println("Second task");
        }
        try {
            Thread.sleep(10);
        } catch (Exception e) {
        }
        while (!thread.isInterrupted()) {
            System.out.println("Third task");
        }
    }

    public Thread start(){
        thread = new Thread(this);
        thread.start();
        return thread;
    }


    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyTask().start();
        Thread.sleep(1000);
        t.interrupt();
        Thread.sleep(1000);
        t.interrupt();
        Thread.sleep(1000);
        t.interrupt();
    }

}

查看 Thread.sleep(long)

上的 Javadoc

Throws: InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

因此,添加 sleep 以及捕获(和忽略)任何异常都会导致观察到的行为。

示例:

没有 sleep():

  • 线程以 interrupted = false 开始,因此第一个循环 运行s
  • 线程被中断,即现在 interrupted = true
  • 第一个循环检查 interrupted 但不检查 运行(再次)
  • 第二个循环检查 interrupted 而根本不检查 运行
  • 第 3 次循环检查 interrupted 而根本不检查 运行
  • 完成

随着sleep()

  1. 线程开始于 interrupted = false
  2. 循环 1:

    • 检查条件并执行正文,因为 interrupted = false
    • 线程被中断,即现在 interrupted = true
    • while 条件被检查但是这次 interrupted = true 所以循环结束
    • sleep() 被调用,由于线程已被中断,因此抛出异常并再次 interrupted = false
    • 异常被捕获(并被忽略),因此继续正常执行
  3. 循环 2 和循环 3 重复步骤 2

  4. 完成

引用自Interrupts

When a thread checks for an interrupt by invoking the static method Thread.interrupted, interrupt status is cleared. The non-static isInterrupted method, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.

含义:将您的代码从 thread.isInterrupted() 更改为 Thread.interrupted(),然后重试。

循环之间的 sleep() 也会通过立即抛出 InterruptedException 来清除该标志(因为当前线程 已被 中断)