JavaRush/Курси/Модуль 2. Java Core/Зупиніть бурхливий потік: офіційна версія

Зупиніть бурхливий потік: офіційна версія

Відкрита

— Привіт, Аміго! Погодься, з цим 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) всі винятки, що виникли.

Ніхто не гарантує, що потік можна зупинити. Він може зупинитися лише сам.

Коментарі (4)
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
10 жовтня 2025, 18:53
1. Розберися, що робить програма. 2. Реалізуй логіку метода run таким чином, щоб кожну секунду через пробіл видавався відлік починаючи з numSeconds до 1, а потім слово [Марш!] (див. приклади). 3. Якщо потік працює 3.5 секунди або більше, перерви його методом interrupt і всередині потоку виведи в консолі слово [Перервано!]. Приклад для numSeconds=4 : "4 3 2 1 Перервано!" 4. Якщо потік працює менше ніж 3.5 секунди, він має завершитися замостійно. Пример для numSeconds=3 : "3 2 1 Марш!" PS: метод sleep викидає InterruptedException. Требования: • Метод run класу RacingClock повинен містити цикл. • Об'єкт класу RacingClock кожну секунду має зменшувати значення змінної numSeconds на одиницю. • Метод main повинен викликати Thread.sleep(3500). • Метод main повинен викликати метод interrupt в об'єкта clock. • Якщо numSeconds дорівнює 3, то програма має виводити "3 2 1 Марш!". • Якщо numSeconds дорівнює 4, то програма має виводити "4 3 2 1 Перервано!". public class Solution { public static volatile int numSeconds = 3; public static void main(String[] args) throws InterruptedException { RacingClock clock = new RacingClock(); Thread.sleep(3500); clock.interrupt(); //напишіть тут ваш код } public static class RacingClock extends Thread { public RacingClock() { start(); } public void run() { try { for (int i = numSeconds; i > 0 ; i--) { System.out.print( i + " "); Thread.sleep(1000); } System.out.print("Марш!"); } catch (Exception e) { System.out.print("Перервано!"); } //напишіть тут ваш код } } } И что ему не так понять не могу.
10 жовтня 2025, 19:06
Ну и что за прикол, а какая разница через фор или вайл. Но через вайл принимает, а через фор хрен тебе.)))
Кирило
Рівень 43
25 листопада 2024, 14:33
В задачі 2 поламані тести
Сергій
Рівень 50
8 червня 2025, 12:42
Та ні, працює