【问题标题】:Single Thread.interrupt() interrupts more than onceSingle Thread.interrupt() 多次中断
【发布时间】:2016-03-25 03:32:24
【问题描述】:

我创建了 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();
    }

}

【问题讨论】:

    标签: java multithreading interrupt


    【解决方案1】:

    查看Thread.sleep(long)上的Javadoc

    抛出:InterruptedException - 如果任何线程中断了当前线程。 当这个异常抛出时,当前线程的中断状态被清除

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

    例子:

    没有sleep():

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

    sleep()

    1. 线程以interrupted = false开头
    2. 循环 1:

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

    4. 完成

    【讨论】:

      【解决方案2】:

      引用Interrupts

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

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

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

      【讨论】:

      • 你想说thread.isInterrupted()到Thread.interrupted()
      猜你喜欢
      • 2013-01-29
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多