Вопрос по java, multithreading, interrupt – Методы, которые сбрасывают флаг Thread.interrupt ()

18

Недавно я унаследовал большое Java-приложение, в котором практически отсутствует безопасность потоков. В настоящее время я работаю над тем, чтобы все потоки правильно обрабатывали прерывания, а не использовали очень плохиеThread.stop().

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

В настоящее время я знаю, что следующее очистит флаг прерывания:

<code>Thread.interrupted()
Thread.sleep(long)
Thread.join()
Thread.join(long)
Object.wait()
Object.wait(long)
</code>

Что еще мне не хватает? Спасибо

Ваш Ответ

3   ответа
14

InterruptedException (+ Thread.interrupted()) очищает флаг прерывания.

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

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

there that clears the interrupt flag.

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

Thread.interrupted()
Thread.isInterrupted(true) -- added to your list

По этой причинеThread.currentThread().isInterrupted() всегда следует использовать вместо

Следующие методы очистят прерванный флагimmediately бросаниеInterruptedException либо если они были вызваны, а затем поток был прерванor если нить былаalready прервано и затем они были вызваны (см. код джунта ниже). Так что не метод очищает флаг, а вызывает исключение.

Thread.sleep(long)
Thread.sleep(long, int) – added to your list
Thread.join()
Thread.join(long)
Thread.join(int, long) – added to your list
Object.wait()
Object.wait(long)
Object.wait(int, long) – added to your list
BlockingQueue.put(...) – added to your list
BlockingQueue.offer(...) – added to your list
BlockingQueue.take(...) – added to your list
BlockingQueue.poll(...) – added to your list
Future.get(...) – added to your list
Process.waitFor() – added to your list
ExecutorService.invokeAll(...) – added to your list
ExecutorService.invokeAny(...) – added to your list
ExecutorService.awaitTermination(...) – added to your list
CompletionService.poll(...) – added to your list
CompletionService.take(...) – added to your list
CountDownLatch.await(...) – added to your list
CyclicBarrier.await(...) – added to your list
Semaphore.acquire(...) – added to your list
Semaphore.tryAcquire(...) – added to your list
Lock.lockInteruptibly() – added to your list
Lock.tryLock(...) – added to your list

Please note что правильная картина сany код, который ловитInterruptedException это немедленно прервать поток. Мы делаем это в случае, если другие полагаются наthread.isInterrupted() метод:

try {
    ...
} catch (InterruptedException e) {
    // immediately re-interrupt the thread
    Thread.currentThread().interrupt();
    // log the exception or [likely] quit the thread
}

Код JUnit, который демонстрирует кое-что из этого:

assertFalse(Thread.currentThread().isInterrupted());
// you can do this from another thread by saying: someThread.interrupt();
Thread.currentThread().interrupt();
// this method does _not_ clear the interrupt flag
assertTrue(Thread.currentThread().isInterrupted());
// but this one _does_ and should probably not be used
assertTrue(Thread.interrupted());
assertFalse(Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
assertTrue(Thread.currentThread().isInterrupted());
try {
    // this throws immediately because the thread is _already_ interrupted
    Thread.sleep(1);
    fail("will never get here");
} catch (InterruptedException e) {
    // and when the InterruptedException is throw, it clears the interrupt
    assertFalse(Thread.currentThread().isInterrupted());
    // we should re-interrupt the thread so other code can use interrupt status
    Thread.currentThread().interrupt();
}
assertTrue(Thread.currentThread().isInterrupted());
1

ch.qos.logback.core.AsyncAppenderBase до версии 1.1.4 перехватывает и глотает InterruptedException без сброса флага в потоке.

Таким образом, если вы используете что-либо, что направляет к этому логгеру (например, slf4j), он будет молча использовать ваш статус прерывания потока. Потому что, я имею в виду, кто не проверяет состояние прерывания потока до и после каждой возможной операции журнала?

Похожие вопросы