Single thread.interrupt()会多次中断。

4

我创建了MyTask,其中在run()中有三个任务需要执行。我试图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
问题是:为什么只有当我添加sleep()时,Thread.interrupts()才能正常工作?
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();
    }

}
2个回答

3
引用自Interrupts

当线程通过调用静态方法Thread.interrupted检查中断时,中断状态将被清除。非静态的isInterrupted方法用于查询另一个线程的中断状态,但不会改变中断状态标志。

意思是:将您的代码从thread.isInterrupted()更改为Thread.interrupted(),然后再试一次。
在循环之间的sleep()也将立即抛出InterruptedException(因为当前线程已经被中断),从而清除该标志。

你想要将 thread.isInterrupted() 改为 Thread.interrupted()。 - Rustam

0

查看关于Thread.sleep(long)的Javadoc

如果任何线程中断了当前线程,将抛出InterruptedException。当抛出此异常时,“当前线程”的中断状态将被清除。

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

示例:

没有sleep()

  • 线程启动时interrupted = false,因此第1个循环运行
  • 线程被中断,即现在interrupted = true
  • 第1个循环检查interrupted并且不运行(再次)
  • 第2个循环检查interrupted并且根本不运行
  • 第3个循环检查interrupted并且根本不运行
  • 完成

使用sleep()

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

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

  4. 完成

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接