Java - проблема с потоками - PullRequest
4 голосов
/ 03 мая 2010

Мой вопрос касается всех тех методов (включая Thread.sleep(...)), которые выдают InterruptedException.

Я нашел заявление в учебнике Sun о том, что

InterruptedException - это исключение, которое sleep генерирует, когда другой поток прерывает текущий поток, пока спящий режим активен.

Значит ли это, что прерывание будет игнорироваться, если sleep не активен во время прерывания?

Предположим, у меня есть две темы: threadOne и threadTwo. threadOne создает и запускает threadTwo. threadTwo выполняет исполняемый файл, метод запуска которого выглядит примерно так:

public void run() {
    :
    :
    try {
        Thread.sleep(10 * 1000);
    } catch (InterruptedException e) {
        return;
    }
    :
    :
    : // In the middle of two sleep invocations
    :
    :
    try {
        Thread.sleep(10 * 1000);
    } catch (InterruptedException e) {
        return;
    }
    :
    :
}

После создания потока threadOne прерывает threadTwo. Предположим, что threadTwo находится в середине двух вызовов сна во время прерывания (когда не активирован ни один метод сна), а затем второй метод сна выдает InterrupteException, как только он будет вызван?

Если нет, то будет ли это прерывание игнорироваться вечно?

Как быть уверенным, что threadTwo всегда будет знать о прерывании (не имеет значения, активен ли один из методов сна) или нет?

Ответы [ 4 ]

3 голосов
/ 03 мая 2010

Из Javadoc:

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

Если этот поток заблокирован в I / O операция на прерываемой канал, то канал будет закрыто, статус прерывания потока будет установлен, и поток будет получить исключение ClosedByInterruptException.

Если эта тема заблокирована в Селектор, а затем прерывание потока статус будет установлен, и он вернется сразу из выбора операция, возможно, с ненулевым значение, как будто селектор метод пробуждения.

Если ни одно из предыдущих условий держи тогда прерывание этой нити статус будет установлен.

Это означает, что вы должны проверить статус прерывания, чтобы убедиться, что ваш поток знает о прерывании. Это можно сделать двумя способами: isInterrupted () и interrupted (). Последний очищает прерванный статус.

Примерно так:

while(!Thread.interrupted()) {
  ...
  try {
    Thread.sleep(10 * 1000);
  } catch (InterruptedException e) {
    return;
  }
}
2 голосов
/ 03 мая 2010

Документация Java немного вводит в заблуждение. Если статус прерывания установлен, вызов sleep() для этого потока вызовет немедленный выброс InterruptException.

Это применимо, даже если поток был прерван до вызова sleep().

Как указано выше, вы также можете проверить с помощью Thread.isInterrupted(), хотите ли вы обрабатывать прерывания самостоятельно.

2 голосов
/ 03 мая 2010

В Windows JDK от Sun поток на самом деле выдает InterruptedException при вводе sleep():

public static final void main(String args[]) throws Exception {
    final Thread main = Thread.currentThread();
    Thread t = new Thread() {
        @Override
        public void run() {
            main.interrupt();
        }
    };
    t.start();
    t.join();
    Thread.sleep(1000);
    System.out.println("Not interrupted!");
}

Документация API sleep() может интерпретироваться как означающая, что это обязательное поведение:

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

Но это не очень понятно, поэтому я бы не стал зависеть от этого и вместо этого проверил isInterrupted()вручную.

0 голосов
/ 03 мая 2010

InterruptException представляет интерес только во время сна потока. Он не будет вызван последующим вызовом sleep (), если поток был прерван где-либо ранее. Только прерывание во время sleep () имеет значение, потому что оно прерывает именно этот вызов sleep ().

...