Прерывание потока в Java
Жёстко «убить» чужой поток в Java нельзя: это ломало бы
инварианты и блокировки. Вместо этого другой поток
ставит флаг прерывания методом interrupt().
Задача должна периодически проверять его и завершаться
аккуратно.
Проверка идёт через Thread.currentThread().isInterrupted()
или статический Thread.interrupted(), который
сбрасывает флаг после чтения. В циклах чаще используют
isInterrupted(), чтобы не терять сигнал.
Цикл, который выходит по флагу:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("tick");
}
System.out.println("stopped");
});
worker.start();
Thread.sleep(10);
worker.interrupt();
worker.join();
}
}
После interrupt() цикл завершится, worker
напечатает stopped. Без проверки флага поток
крутился бы бесконечно.
Если worker спит, interrupt() будит его и
sleep бросает InterruptedException:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread sleeper = new Thread(() -> {
try {
Thread.sleep(60_000);
} catch (InterruptedException e) {
System.out.println("wake on interrupt");
Thread.currentThread().interrupt();
}
});
sleeper.start();
Thread.sleep(100);
sleeper.interrupt();
sleeper.join();
}
}
В catch флаг прерывания сбрасывается, поэтому
его восстанавливают вызовом interrupt() на
текущем потоке, если прерывание нужно учесть выше
по стеку.
Запустите поток с циклом, печатающим "work",
пока не установлен interrupt. Через 50 мс
прервите его из main, дождитесь join
и выведите "main free".