Ответ 1
Альтернативой вызову stop является использование прерывания для подачи сигнала в поток, который вы хотите, чтобы он завершил то, что он делает. (Это предполагает, что поток, который вы хотите остановить, хорошо себя ведет, если он игнорирует InterruptedExceptions, поедая их сразу же после их броска и не проверяя прерванный статус, тогда вы возвращаетесь к использованию 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 (используя его для выхода из цикла). Прерывание - это одно место, где можно использовать исключение для управления потоком, вот и все.
-
Настройка прерывания по текущему потоку в блоке catch является технически лучшей практикой, но для этого примера излишняя, потому что больше нет необходимости устанавливать флаг прерывания.
Некоторые замечания о размещенном коде:
-
Опубликованный пример неполный, но ссылка на текущий поток в переменной экземпляра кажется плохой идеей. Он будет инициализирован любым потоком, создающим объект, а не потоком, выполняющим метод run. Если один и тот же экземпляр Runnable выполняется более чем в одном потоке, переменная экземпляра не будет отражать правильный поток большую часть времени.
-
Проверка наличия живого потока всегда обязательно приведет к истинному (если нет ошибки, когда переменная экземпляра currentThread ссылается на неправильный поток),
Thread#isAlive
является ложным только после завершения потока он не возвращает false только потому, что он был прерван. -
Вызов
Thread#interrupted
приведет к очистке флага прерывания и не имеет смысла здесь, тем более, что возвращаемое значение отбрасывается. Точка вызоваThread#interrupted
- проверить состояние прерванного флага, а затем очистить его, это метод удобства, используемый вещами, которые бросаютInterruptedException
.