Остановка потока
Поток останавливают кооперативно: один код выставляет запрос на прерывание, другой регулярно его замечает, освобождает ресурсы и завершает run().
final class Worker implements Runnable {
private final BlockingQueue<Job> jobs;
Worker(BlockingQueue<Job> jobs) {
this.jobs = jobs;
}
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
process(jobs.take());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
closeResources();
}
}
}
Thread thread = new Thread(new Worker(queue));
thread.start();
thread.interrupt();Семантика interrupt
interrupt()выставляет флаг запроса.isInterrupted()читает его и не очищает.Thread.interrupted()читает флаг текущего потока и очищает.sleep,wait,joinи многие блокирующие методы при прерывании бросаютInterruptedExceptionи очищают флаг.
Если метод не может завершиться и обязан пробросить обычный результат, он обычно восстанавливает флаг: Thread.currentThread().interrupt(). Если метод действительно обработал отмену и выходит из верхнего уровня run, восстановление менее важно, но делает причину завершения наблюдаемой.
Не всякая операция мгновенно реагирует на interrupt. Для закрытия сокета, канала или стороннего клиента может потребоваться их собственный API отмены.
Warning
Thread.stop()небезопасен: асинхронно бросает исключение и освобождает мониторы в произвольной точке, оставляя данные в промежуточном состоянии.suspend()иresume()тоже не использовать.
На собеседовании
- Прерывание — команда на убийство? Нет, кооперативный запрос.
- Почему нельзя молча проглатывать
InterruptedException? Теряется сигнал отмены, вышестоящий код продолжает ждать. - Как восстановить флаг?
Thread.currentThread().interrupt(). - Что делает
Thread.interrupted()? Читает и очищает флаг текущего потока. - Всегда ли interrupt разблокирует I/O? Нет, зависит от API.