Java: Разница в использовании между Thread.interrupted() и Thread.isInterrupted()? - программирование
Подтвердить что ты не робот

Java: Разница в использовании между Thread.interrupted() и Thread.isInterrupted()?

Вопрос Java. Насколько я знаю, есть два способа проверить внутри потока, был ли поток принят сигнал прерывания, Thread.interrupted() и Thread.isInterrupted(), и единственная разница между ними заключается в том, что бывший сбрасывает внутренний прерванный флаг.

До сих пор я всегда использовал Thread.isInterrupted() и никогда не испытывал никаких проблем с этим. С другой стороны, большинство учебных пособий, которые я видел, рекомендуют использовать Thread.interrupted(). Есть ли какая-то конкретная причина для этого?

4b9b3361

Ответ 1

interrupted() является static и проверяет текущий поток. isInterrupted() - это метод экземпляра, который проверяет объект Thread, на который он вызывается.

Общей ошибкой является вызов статического метода в экземпляре.

Thread myThread = ...;
if (myThread.interrupted()) {} // WRONG! This might not be checking myThread.
if (myThread.isInterrupted()) {} // Right!

Другое отличие состоит в том, что interrupted() также очищает статус текущего потока. Другими словами, если вы вызываете его дважды подряд, и поток не прерывается между двумя вызовами, второй вызов возвращает false, даже если первый вызов возвращен true.

Javadocs расскажет вам о таких важных вещах; используйте их часто!

Ответ 2

Если вы используете interrupted, то, что вы спрашиваете, "я был прерван с момента последнего запроса?"

isInterrupted указывает, прерывается ли этот поток, который вы вызываете.

Ответ 3

Метод interrupted() - это метод класса, который всегда проверяет текущий поток и очищает флаг прерывания. Другими словами, второй вызов interrupted() вернет false.

Метод isInterrupted() - это метод экземпляра; он сообщает о статусе потока, на который он вызывается. Кроме того, он не очищает флаг прерывания. Если флаг установлен, он останется установленным после вызова этого метода.

Ответ 4

Прерывание потоков в Java является рекомендательным. Если вы вызовете Thread.interrupt(), тогда он установит флаг и отменит любые незавершенные задачи ввода-вывода (которые будут вызывать InterruptedException). Однако для обработки этого процесса в потоке выполняется код. Это называется реализацией политики прерывания потока.

Однако, поскольку состояние прерывания Thread является общим, важно, чтобы любая такая обработка была Thread Safe. Вы не хотите, чтобы какой-то другой поток отключился и пытался что-то сделать с прерванным флагом, если вы его обрабатываете. По этой причине флаг Thread.interrupted() делает этот атомный так, что он используется, когда вы хотите сказать: "Если этот поток был прерван, я буду иметь дело с ним). Обычно это будет включать очистку некоторых ресурсов. вы должны, вероятно, распространять прерванный флаг, чтобы вызывающие могли его обрабатывать. Вы можете сделать это, вызвав Thread.interrupt.

Ответ 5

Вот несколько примеров того, как вы можете использовать эти методы:

  • Если вы пишете собственный пул потоков, вам может потребоваться проверить прерванный статус на одном из потоков, которыми вы управляете. В этом случае вы вызываете managedThread.isInterrupted(), чтобы проверить его прерванный статус.

  • Если вы пишете собственные обработчики InterruptedException, которые не сразу перезапускают эквивалентное исключение через Thread.currentThread().interrupt() (например, у вас может быть блок finally после обработчиков исключений), вы можете проверить, поток, который вы в настоящее время выполняете, был прерван внешним вызовом или InterruptedException. В этом случае вы должны проверить логическое значение Thread.interrupted(), чтобы проверить состояние текущего потока.

Второй метод действительно мне когда-нибудь полезен в ситуациях, когда я боюсь, что кто-то написал eater на более низком уровне, который, по большому счету, тоже съел InterruptedException.

Ответ 6

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

Я понимаю, что isInterrupted (метод экземпляра) редко используется - в основном для ведения журналов и отладки и т.п. Он дает только моментальный снимок флага в данном потоке, который вскоре может быть устаревшим.

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

Итак, в качестве примера, если ваша задача выглядит примерно так:

void process(Things[] things) throws InterruptedException {
    for (Thing thing : things) {
        thing.twiddle(); // this call throws InterruptedException
    }
}

тогда вам не нужно ничего делать; если кто-то называет Thread.interrupt в вашем потоке, во время текущего или следующего twiddle вызова InterruptedException будет сброшен и остановит вашу задачу.

Но что, если twiddle не бросает InterruptedException и вообще не может быть прервано посередине? Скажем, каждый такой вызов занимает 100 мс, но things.length может быть 100. Тогда process может быть заблокирован на 10 секунд, даже если кто-то пытается его прервать, что может быть неприемлемым в вашем приложении. Таким образом, вы можете явно проверить прерывания:

void process(Things[] things) {
    if (Thread.interrupted()) {
        return;
    }
    for (Thing thing : things) {
        thing.twiddle();
    }
}

Здесь вы можете понять, почему важно, чтобы interrupted атомически проверял и очищал флаг: вы используете его, чтобы подтвердить получение сообщения, что кто-то вежливо попросил вас остановить как можно скорее. (В этом случае в пределах примерно 100 мс запроса.) Вы также можете понять, почему это должен быть статический метод, действующий на текущий поток: он имеет смысл только в контексте проверки того, должен ли быть остановлен окружающий код.

Конечно, если вызывающий объект process предполагает, что он заканчивается, просто return ing, как показано здесь, будет вводить в заблуждение. Таким образом, вы можете захотеть сделать process количество возвращаемых нами деталей, или, возможно, более целесообразно исключить исключение:

void process(Things[] things) throws InterruptedException {
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }
    for (Thing thing : things) {
        thing.twiddle();
    }
}

В этом случае вызывающий получает (отмеченное) исключение, информирующее их о том, что кто-то еще попросил прекратить обработку посередине. Обычно вызывающий пользователь должен просто исключить исключение из стека вызовов.

Вы также можете заново запереть себя, если не сможете остановить свою текущую задачу, но вам нужно знать, что запрос на ее остановку пришел, например, чтобы сократить оставшуюся часть работы:

void process(Things[] things) {
    boolean twiddleFully = true;
    if (twiddleFully && Thread.interrupted()) {
        twiddleFully = false;
        Thread.currentThread().interrupt();
    }
    for (Thing thing : things) {
        thing.twiddle(twiddleFully);
    }
}

Здесь мы можем обработать оставшиеся вещи быстрее, но все равно завершить цикл и снова включить прерванный флаг, чтобы наш вызывающий абонент мог решить его обработать.

Ответ 7

interrupted() метод статический метод потока класса проверяет текущий поток и очищает флаг прерывания .i.e. второй вызов прерывания() вернет false.

isInterrupted() - метод экземпляра; он сообщает о статусе потока, на который он вызывается. он не очищает флаг прерывания.

Если флаг установлен, он останется установленным после вызова этого метода.

Thread myThread = ...;
if (myThread.interrupted()) {} //error

Thread.interrupted()//right

if (myThread.isInterrupted()) {} // Right

Ответ 8

Это старый вопрос, и, пройдя ответы, я чувствую, что все еще есть недостающая информация. Здесь моя попытка заполнить эту пропавшую часть информации.

Начиная с Java 5, вы обычно обращаетесь к Threads только косвенно. Инфарктные потоки, созданные из java.util.Executor framework, рассматриваются в библиотечных методах. Эти потоки часто называют сущностями, которые блокируют природу как Future.get(). т.е. get() до тех пор, пока результат не будет доступен. Теперь существует перегруженная форма get(), которая принимает значение тайм-аута и вызов этого метода означает, что поток хочет подождать период, равный таймауту для возврата get () значение, если эта задача не может быть отменена с помощью Future.cancel(). Поэтому эти методы серьезно относятся к перерыву в том, что, как только они обнюхивают прерывание, они также бросают проверенное исключение прерывания. Следовательно, вызывающие лица вынуждены обрабатывать InterruptionException. Поскольку они уже распространяют InterruptedException, которое передает прерванный статус, имеет смысл блокировать mehthods также очистить прерванный статус, вызвав Thread.interrupt(). В противном случае нарушается контракт InterruptedException.

Однако, если вы имеете дело с необработанными потоками, которые, как правило, не рекомендуются сейчас, вы должны быть осторожны при вызове статического метода interrupted(), потому что если вы вызываете его дважды в строке и поток не прерывается между двумя вызовами, второй вызов будет возвращать false, даже если первый вызов вернулся true.