使用Thread.currentThread()。isInterrupted()与Thread.sleep()

时间:2015-06-24 07:42:16

标签: java multithreading concurrency interrupt interrupted-exception

我有一个调用work()方法的线程,这是一个简单的while(true)-loop,如下所示;

public void work() throws InterruptedException {
    while (true) {
        // PART A
        if (Thread.currentThread().isInterrupted()) {
            System.out.println("....run()::work::PART A::isInterrupted():" + Thread.currentThread().isInterrupted());
            Thread.sleep(2000);
        }

        // Is it possible to make the below code executable at runtime when thread is interrupted?
        // PART B
        if (Thread.currentThread().isInterrupted()) {
            System.out.println("....run()::work::PART B::isInterrupted():" + Thread.currentThread().isInterrupted());
            Thread.sleep(2000);
        }
    }
}

我运行这个线程实例并在一段时间后使用Thread.sleep()方法从main中断线程。当我更改延迟时,我希望在主线程中断线程时点击注释部分,但我只看到下面的输出;

....run()::Work::starting
.main()::interrupting thread t
.main()::leaving
....run()::work::PART A::isInterrupted():true
....run()::Work::ERROR::INTERRUPTED

我的简单问题是,是否可以执行work()方法的第二部分(B部分),如果没有,为什么?

完整的演示如下;

public class GeneralInterrupt implements Runnable {
    public void run() {
        try {
            System.out.println("....run()::Work::starting");
            work();
            System.out.println("....run()::Work::ended");
        } catch (InterruptedException x) {
            System.out.println("....run()::Work::ERROR::INTERRUPTED");
            return;
        }
        System.out.println("....run()::Work::leaving normally");
    }

    public void work() throws InterruptedException {
        while (true) {
            // PART A
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("....run()::work::PART A::isInterrupted():" + Thread.currentThread().isInterrupted());
                Thread.sleep(2000);
            }

            // Is it possible to make the below code executable at runtime when thread is interrupted?
            // PART B
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("....run()::work::PART B::isInterrupted():" + Thread.currentThread().isInterrupted());
                Thread.sleep(2000);
            }
        }
    }

    public static void main(String[] args) {
        Thread t = new Thread(new GeneralInterrupt());
        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException x) {
        }
        System.out.println(".main()::interrupting thread t");
        t.interrupt();
        System.out.println(".main()::leaving");
    }
}

另请注意,如果从A和B部分删除“Thread.sleep(2000)”行,则输出为

....run()::work::PART B::isInterrupted():false
....run()::work::PART B::isInterrupted():false
....run()::work::PART B::isInterrupted():false
....run()::work::PART B::isInterrupted():false
....run()::work::PART A::isInterrupted():true
....run()::work::PART A::isInterrupted():true
....run()::work::PART A::isInterrupted():true
....run()::work::PART A::isInterrupted():true
....run()::work::PART A::isInterrupted():true

任何人都可以解释为什么Thread.sleep()方法在work()方法中以这种方式运行。

3 个答案:

答案 0 :(得分:0)

当您中断线程并且它在sleep方法中时,sleep将抛出InterruptedException。您不处理此异常。它会传播到您的run方法,并且您的while循环会退出。

您需要使用try / catch包围sleep并抓住InterruptedException。如果希望Thread.currentThread().interrupt()在异常后返回true,则还必须确保在捕获isInterrupted()后调用 if (Thread.currentThread().isInterrupted()) { System.out.println("....run()::work::PART A::isInterrupted():" + Thread.currentThread().isInterrupted()); try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } ,因为异常将重置中断标志。像这样:

Thread

答案 1 :(得分:0)

根据Oracle Tutorial,中断线程是线程发出信号以结束其当前工作并执行其他操作(如终止)的信号:

  

中断是一个线程的指示,它应该停止它正在做的事情并做其他事情。由程序员决定线程如何响应中断,但线程终止是很常见的。这是本课中强调的用法。

因此,通常应该可以在中断后继续。

根据中断的JavaDoc,它取决于线程被中断的位置:

  

如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long)时阻塞了这个线程,int), sleep(long),或者sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到一个 InterruptedException的。 (我强调)

这就是使用sleep(2000)时出现异常的原因。

答案 2 :(得分:0)

Thread.isInterrupted() doesn't clear the interrupted status of the thread。因此,当您致电sleep()时,会抛出InterruptedException。您需要致电Thread.interrupted()而不是Thread.currentThread().isInterrupted()

然而,这意味着B部分仅在A部分睡眠期间发生中断时执行,这似乎是您想要的。如果在A部分运行时需要B部分运行,则将其放入同一个块而不是在第二次测试之后。