单线程中断()多次



我创建了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

问题是:为什么只有添加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();
    }
}

引用中断:

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

意思是:将代码从thread.isInterrupted()更改为Thread.interrupted(),然后重试。

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

查看Thread.sleep(long) 上的Javadoc

抛出:InterruptedException-如果有线程中断了当前线程当抛出此异常时,当前线程的中断状态将被清除

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

示例:

sleep():

  • 线程从interrupted = false开始,因此运行第一个循环
  • 线程被中断,即现在interrupted = true
  • 第1个循环检查interrupted并且没有运行(再次)
  • 第二个循环检查interrupted,根本不运行
  • 第三个循环检查interrupted,根本不运行
  • 已完成

使用sleep()

  1. 线程从interrupted = false开始
  2. 回路1:

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

  4. 已完成

最新更新