Поток прерывается вызовом interrupt(), но Thread.isInterrupted() возвращает false

Я тестирую InterruptedException со следующим тестовым кодом:

Runnable runMe = new Runnable() {
    @Override
    public void run() {
        for(int i=0; i<6; i++) {
            System.out.println("i = "+i);
            if(i==3) {
                System.out.println("i==3, Thread = " 
                +Thread.currentThread().getId());
                //I invoke interrupt() on the working thread.
                Thread.currentThread().interrupt();
                try {
                    Thread.currentThread().join();
                } catch (InterruptedException e) {
                    //I caught InterruptedException
                    System.out.println(Thread.currentThread().getId() 
                    + " is interrupted!");
                    Thread.currentThread().interrupt();
                }
            }
        }
    }   
};          
Thread workingThread = new Thread(runMe);
workingThread.start();
try {
    workingThread.join();
} catch (InterruptedException e) {
    //Swallow
}
//the following log shows me workingThread.isInterrupted() is false, why?
System.out.println("workingThread(" 
+ workingThread.getId()+") interrupted ? " 
+ workingThread.isInterrupted());

В run() я interrupt() текущий рабочий поток и поймал InterruptedException.

В основном потоке моя последняя строка кода — это System.out.println(...), которая выводит статус прерывания рабочего потока. Поскольку я поймал InterruptedException в run(), я должен был получить сообщение о том, что workingThread.isInterrupted() истина, но я получил ложь, почему?


person user842225    schedule 17.10.2014    source источник
comment
Как я отметил в вашем предыдущем вопросе, я сильно подозреваю, что потоки, которые сейчас мертвы, никогда не считаются прерванными.   -  person Jon Skeet    schedule 17.10.2014
comment
@nathan Нет sleep здесь. Вы намекаете на то, что что-то в их примере сбрасывает флаг прерывания?   -  person Sotirios Delimanolis    schedule 17.10.2014
comment
вновь открыт, потому что это больше относится к тому, что здесь происходит, чем к тому, почему это работает таким образом, поэтому эти два вопроса кажутся разными.   -  person Nathan Hughes    schedule 17.10.2014


Ответы (1)


В руководстве по параллелизму Java говорится (выделено мною):

Флаг состояния прерывания

Механизм прерывания реализован с использованием внутреннего флага, известного как состояние прерывания. Вызов Thread.interrupt устанавливает этот флаг. Когда поток проверяет наличие прерывания, вызывая статический метод Thread.interrupted, статус прерывания сбрасывается. Нестатический метод isInterrupted, который используется одним потоком для запроса состояния прерывания другого, не изменяет флаг состояния прерывания.

По соглашению, любой метод, который завершает работу, вызывая InterruptedException, очищает статус прерывания при этом. Однако всегда возможно, что статус прерывания будет немедленно установлен снова другим потоком, вызвавшим прерывание.

То, что вы видите, это то, что поток прерывается, метод выхода — это соединение (фактически соединение реализуется путем вызова Object.wait, поэтому я ожидаю, что трассировка стека покажет, что ожидание — это метод, из которого выбрасывается исключение), и флаг очищается, как говорится в учебнике.

Обработчик исключения должен решить, следует ли снова установить флаг состояния прерывания потока или нет. Если обработчик не закодирован так, чтобы делать что-то по-другому, по умолчанию предполагается, что исключение было обработано, и больше нет необходимости устанавливать флаг.

документация API для Thread#interrupt согласуется с этим:

Если этот поток заблокирован при вызове методов wait(), wait(long) или wait(long, int) класса Object или методов join(), join(long), join(long, int) , sleep(long) или sleep(long, int) этого класса, то его статус прерывания будет очищен, и он получит InterruptedException.

У меня есть ответ, который более подробно объясняет, почему прерывание было разработано таким образом здесь.

person Nathan Hughes    schedule 17.10.2014