JavaRush /Курсы /Java Core /Остановить бушующий поток: официальная версия

Остановить бушующий поток: официальная версия

Java Core
6 уровень, 9 лекция
Открыта

— Привет, Амиго! Согласись, Элли хорошо придумала с этим Cancel?

— Ага.

— На самом деле нечто подобное существует в классе Thread. Только переменная называется не isCancel, а isInterrupted, и метод остановки, соответственно, не cancel(), а interrupt().

— Да?

— Ага. Вот смотри:

Код Описание
class Clock implements Runnable
    public void run()
        Thread current = Thread.currentThread();


        while (!current.isInterrupted())
            try
                Thread.sleep(1000);
            } catch (InterruptedException e)
                e.printStackTrace();
                current.interrupt();
            }
            System.out.println("Tik");
        }
    }
}
Т.к. много нитей могут вызвать метод run одного объекта, то объект Clock в своем методе run получает объект вызвавшей его нити («текущей нити»).

Класс Clock (часы) будет писать в консоль раз в секунду слово «Tik», пока переменная isInterrupted текущей нити равна false.

Когда переменная isInterrupted станет равной true, метод run завершится.

public static void main(String[] args) throws Exception {
    Clock clock = new Clock();
    Thread clockThread = new Thread(clock);
    clockThread.start();


    Thread.sleep(10000);
    clockThread.interrupt();
}
Главная нить, запускает дочернюю нить – часы, которая должна работать вечно.

Ждет 10 секунд и отменяет задание, вызовом метода interrupt.

Главная нить завершает свою работу.

Нить часов завершает свою работу.

Более того, в методе sleep, который так любят использовать для организации вечного цикла в методе run, есть автоматическая проверка переменной isInterrupted. Если нить вызовет метод sleep, то этот метод сначала проверит, а не установлена ли для текущей (вызвавшей его нити) переменная isInterrupted в true. И если установлена, то метод не будет спать, а выкинет исключение InterruptedException.

— А зачем выкидывать исключение? Не лучше ли тоже просто в цикле вместо isCancel подставить isInterrupted()?

— Во-первых, не всегда в методе run есть цикл. Метод может состоять просто из двух десятков вызовов других методов. Тогда перед вызовом каждого придется добавлять проверку isInterrupted.

Во-вторых, вдруг какой-то метод очень долго исполняется, т.к. делает много разных действий.

В-третьих, выкидывание исключения – это не замена проверке isInterrupted, а скорее удобное дополнение. Выкинутое исключение позволяет быстро раскрутить стек вызовов до самого run.

В-четвертых, метод sleep часто используют, и, получается, к такому полезному методу неявно добавили не менее полезную проверку. Вроде бы никто специально проверку не добавлял, а она есть. Это очень ценно, когда ты используешь много чужого кода и не можешь сам добавить в него проверку.

В-пятых, дополнительная проверка не приводит к снижению производительности. Вызов метода sleep значит, что нить должна ничего не делать (спать), поэтому дополнительная работа никому не мешает.

— Серьёзные аргументы.

— И, наконец, последнее: ты можешь в своем методе run вызывать чужой код, к которому у тебя нет доступа (исходников и/или прав их менять). Он может не иметь проверок на isInterrupted, а также перехватывать с помощью try…catch(Exception e) все возникшие исключения.

Никто не гарантирует, что нить можно остановить. Она может остановиться только сама.

Комментарии (320)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Denis Nkn Уровень 26
17 октября 2026
Так в цикле while переменная isInterrupted или метод isInterrupted()?
TimJohnzz Уровень 22
29 сентября 2026
Для тупых(меня): Если во время выполнения кода в методе run нашего потока(thread, нить) мы вызовем метод interrupt(), то он не прервет наш поток, он просто сообщит JVM, что этот поток должен быть прерван. Поэтому мы должны сами поставить проверку в нашем run на то, вызывался ли interrupt или нет. 1)В цикле это легко, в самом условии проверяем (!Thread.currentThread().isInterrupted) 2)Когда поток находится в sleep(), а нам нужно его прервать, то JVM сама разбудит его и завершит, так как любой sleep() обрабатывается в try catch, и при прерывании потока и выбрасывании исключения, он и завершится(в блоке catch пишем break; и ОБЯЗАТЕЛЬНО возвращаем наш флажок методом .interrupt(), так как при выбрасывании исключения его состояние сбрасывается) 3)если же у нас нет ни цикла, ни sleep(), а огромный блок кода, то делаем ручные проверки через какое то расстояние в коде - if(Thread.currentThread.isInterrupted){... return; }
Grigoryvvv Уровень 28 Expert
4 сентября 2026
05.09.2026 / 26 уровень
nastya_zhadan Уровень 66
8 сентября 2025
Копирую картинку из популярных комментов
Anonymous #3585174 Уровень 33
22 августа 2025
Like
Сайфер Уровень 51
29 июля 2025
1) Метод sleep() ПОСТОЯННО проверяет был ли прерван поток, а не только вначале выполнения этого метода. 2) Метод sleep(), если был прерван поток, выбросит исключение Interrupted Exception. Это исключение, как только будет выброшено, сразу же установит флаг interrupted обратно на false. Поэтому нужно вызывать в блоке catch снова вызов метода interrupt(). Сам по себе, метод interrupt не выбрасывает исключений, он просто установит флаг interrupted в true. Затем дальше по циклу снова идет проверка условия, и вот здесь уже этот цикл прерывается. Я этого не понимал раньше, из-за этого куча проблем было с попыткой врубиться в потоки.
Den Winchester Уровень 32
9 ноября 2025
спасибо, очень помог
Ruslan Gabzalilov Уровень 27
6 февраля 2026
Спасибо добрый человек)
Anonymous #463526 Уровень 7
18 апреля 2025
опять форматирование портит все ((

public static void main(String[] args) throws Exception {
  Clock clock = new Clock();   Thread clockThread = new Thread(clock);   clockThread.start();

  Thread.sleep(10000);
  clockThread.interrupt();
}
Ромушка Роман Уровень 32
20 октября 2024
По поводу прерывания я понял, это не так сложно. Не понял лишь, как быть в итоге с длинными по времени операциями или блоком из вызовов, например, 10-ти функций?
{Java_Shark} Уровень 36
14 октября 2024
++
Alex Уровень 1 Expert
10 октября 2024
Вот как я понял продолжение))

public static void main(String[] args) throws Exception {
   Clock clock = new Clock();
   Thread clockThread = new Thread(clock);
   clockThread.start();
   Thread.sleep(10000);
}
clockThread.interrupt() устанавливает флаг прерывания у потока clockThread, что приводит к тому, что метод isInterrupted() вернет true в цикле while в методе run(). Поток clockThread получит сигнал о прерывании. Если этот поток находится в состоянии ожидания (например, исполняется метод Thread.sleep()), он выбросит InterruptedException. Внутри метода run() класса Clock выполнится блок catch и поток завершит свою работу, так как isInterrupted() вернет true.