-1

假设以下代码使用调试器执行,以便我们可以预测执行顺序。

  • t1 -- 这里 task1 开始处理一些长任务。
  • t2 --- task2 被阻塞 @ Syncronized 语句,因为 task1 持有锁。
  • t3 - task2 被中断但它错过了,因为 task2 正在使用内部锁,因此不能在@同步时被中断。(Renenterant.lockInterruptible() 会抛出 InterruptedExecption)。
  • t4 --- task1 被中断。然而,尽管在 try catch 块中执行了复杂的任务,但从未抛出 InterruptedExecption。这是为什么 ?

代码:

public class TestInteruptibility {
    public static Object lock = new Object();
    public static boolean spin = true;

    public static void main(String[] args) {
        Thread task1 = new Thread(new Task(), "Task1");
        Thread task2 = new Thread(new Task(), "Task2");
        Thread notifier1 = new Thread(new Notifier(), "Notifier1");
        task1.start();
        task2.start();
        task2.interrupt();
        task1.interrupt();
        notifier1.start();
    }
}

class Task implements Runnable {
    public void run() {
        synchronized (TestInteruptibility.lock) {
            System.out.println("Performing Long Task");
            try {
                while (TestInteruptibility.spin) {
                }
                System.out.println("Finsihed Performing Long Task");
                TestInteruptibility.lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("I got interrupted while i was waiting @ wait()");
            }
            System.out.println("Ending Task");
        }
    }
}

class Notifier implements Runnable {
    public void run() {
        synchronized (TestInteruptibility.lock) {
            System.out.println("Performing notification");
            TestInteruptibility.lock.notify();
            System.out.println("Ending notification");
        }
    }
}
4

3 回答 3

3

基本上,interrupt()所做的是在Thread对象中设置一个标志。你需要用isInterrupted(). 然后你就可以处理这个中断信号了。InterruptedException在这种情况下它不会抛出一个。

此外,它还可能导致某些方法,例如 , Thread.sleep(),Object.wait()立即返回并抛出一个InterruptedException. InterruptedException在这种情况下,您可以获得和。

来自Java 并发实践,7.1.1。中断

A good way to think about interruption is that it does not actually interrupt a running thread; it just requests that the thread interrupt itself at the next convenient opportunity. (These opportunities are called cancellation points.) Some methods, such as wait, sleep, and join, take such requests seriously, throwing an exception when they receive an interrupt request or encounter an already set interrupt status upon entry. Well behaved methods may totally ignore such requests so long as they leave the interruption request in place so that calling code can do something with it. Poorly behaved methods swallow the interrupt request, thus denying code further up the call stack the opportunity to act on it.

在您上面的代码中,您没有在等待/睡觉。所以你必须在循环isInterrupted()中自己检查和处理中断信号。while

while (TestInteruptibility.spin) {
    if (Thread.currentThread().isInterrupted()) {
        break;
    }
}

参考:

  1. 为什么中断()不能按预期工作以及它是如何工作的
  2. java.lang.Thread.interrupt() 有什么作用?
于 2013-03-17T06:57:45.347 回答
2

您有一个繁忙的 while 循环,它持有锁(并且永远不会结束,除非您在某处更改自旋的值)。我想 task1 仍在循环中,因此它不会注意到中断。Task2 无法获取锁,因此阻塞。

Task 的实现方式,它只能在循环之后的等待命令期间被中断。

顺便说一句:如果您在不同的线程中使用 spin 数据成员,那么它可能应该被声明为 volatile。出于类似的线程安全原因,应该将 lock 声明为 final。

于 2013-03-17T06:43:03.103 回答
0

当您调用方法时interrupt(),结果取决于此线程当前正在执行的操作。如果它在某些可中断的方法上被阻塞,例如Object.wait(),那么它将立即被中断,这意味着InterruptedException将被抛出到线程中。如果线程没有被阻塞,但正在做一些计算,或者它在某些不可中断的方法上被阻塞,例如InputStream.read()thenInterruptedException不会被抛出,而是interrupted在线程上设置标志。这个标志将导致InterruptedException下一次线程将调用一些可中断的方法,但不是现在。

在您的情况下,线程在无限空循环task1task2旋转,因此不会被任何可中断的方法阻塞,因此当您调用interrupt()时,不会InterruptedException在该线程内抛出 no ,但interrupted只是设置了标志。您可能应该将任务代码更改为如下所示:

while (TestInteruptibility.spin && !Thread.interrupted ()) {
}

那么只要有人调用interrupt任务线程,你就会退出循环。

于 2013-03-17T07:00:05.827 回答