Альтернативой вызову stop является использование прерывания, чтобы сообщить потоку, что вы хотите, чтобы он завершил свою работу. (Предполагается, что поток, который вы хотите остановить, ведет себя хорошо, если он игнорирует исключения InterruptedException, поедая их сразу после их выброса, и не проверяя состояние прерывания, тогда вы возвращаетесь к использованию stop ().)
Вот код, который я написал как ответ на вопрос о потоке здесь , это пример того, как работает прерывание потока:
public class HelloWorld {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(new Runnable() {
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(5000);
System.out.println("Hello World!");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
thread.start();
System.out.println("press enter to quit");
System.in.read();
thread.interrupt();
}
}
О чем нужно знать:
Прерывание приводит к немедленному броску sleep()
и wait()
, в противном случае вы застряли в ожидании, когда пройдет время сна.
Обратите внимание, что нет необходимости в отдельном логическом флаге.
Остановленный поток взаимодействует, проверяя статус прерывания и перехватывая InterruptedExceptions вне цикла while (используя его для выхода из цикла). Прерывание - это единственное место, где можно использовать исключение для управления потоком, и в этом весь смысл.
Установка прерывания для текущего потока в блоке перехвата является технически наилучшей практикой, но в этом примере это излишне, поскольку нет ничего другого, для чего требуется установка флага прерывания.
Несколько замечаний по поводу размещенного кода:
Опубликованный пример неполон, но помещать ссылку на текущий поток в переменную экземпляра кажется плохой идеей. Он будет инициализирован для любого потока, создающего объект, а не для потока, выполняющего метод run. Если один и тот же экземпляр Runnable выполняется в более чем одном потоке, то переменная экземпляра большую часть времени не будет отображать нужный поток.
Проверка того, является ли поток работоспособным, всегда всегда будет приводить к истине (если только нет ошибки, когда переменная экземпляра currentThread ссылается на неправильный поток), Thread#isAlive
ложна только после завершения потока выполнение не возвращает false только потому, что оно было прервано.
Вызов Thread#interrupted
приведет к очистке флага прерывания и здесь не имеет смысла, тем более что возвращаемое значение отбрасывается. Смысл вызова Thread#interrupted
состоит в том, чтобы проверить состояние прерванного флага, а затем очистить его, это удобный метод, который используется для вещей, которые выдают InterruptedException
.