— Привіт, Аміго! Погодься, з цим Cancel добре придумано?
— Так.
— Насправді щось схоже існує у класі Thread. Тільки змінна називається не isCancel, а isInterrupted, і метод зупинки, відповідно, не cancel(), а interrupt().
— Так?
— Так. Ось дивись:
Код | Опис |
---|---|
|
Оскільки багато потоків можуть викликати метод run одного об'єкта, то об'єкт Clock у своєму методі run отримує об'єкт, що викликав його потоки («поточний потік»).
Клас Clock (годинник) буде писати у консолі раз на секунду слово «Tik», поки змінна isInterrupted поточного потоку дорівнює false. Коли змінна isInterrupted буде дорівнювати true, метод run завершиться. |
|
Головний потік, що запускає дочірній потік – годинник, який може працювати вічно.
Чекає 10 секунд і скасовує завдання за допомогою виклику методу interrupt. Головний потік завершує свою роботу. Потік годинника завершує свою роботу. |
Більш того, в методі sleep, який так полюбляють використовувати для організації вічного циклу у методі run, є автоматична перевірка змінної isInterrupted. Якщо потік викликає метод sleep, то цей метод спершу перевірить, чи не встановлена для поточного (потоку, що його викликав) змінна isInterrupted в true. Якщо встановлена, то метод не буде спати, а викине виняток InterruptedException.
— А навіщо викидати виняток? Чи не краще просто у циклі замість isCancel вписати isInterrupted()?
— По-перше, не завжди у методі run є цикл. Метод може складатися просто з двох десятків викликів інших методів. Тоді перед викликом кожного доведеться додавати перевірку isInterrupted.
По-друге, раптом якийсь метод дуже довго виконується, оскільки робить багато різних дій.
По-третє, викидання винятку – це не заміна перевірки isInterrupted, а швидше зручне доповнення. Викинутий виняток дозволяє швидко розкрутити стек викликів до самого run.
По-четверте, метод sleep часто використовують, і, виявляється, до такого корисного методу було додано не менш корисну перевірку. Ніби ніхто спеціально перевірку не додавав, а вона є. Це дуже цінно, коли ви використовуєте багато чужого коду, і не можете додати до нього перевірку.
По-п'яте, додаткова перевірка не призводить до зниження продуктивності. Виклик методу sleep означає, що потік повинен нічого не робити (спати), тому додаткова робота йому не заважає.
— Серйозні аргументи.
— І, нарешті, останнє: ти можеш у своєму методі run викликати чужий код, до якого в тебе немає доступу (джерел та/або прав їх змінювати). Він може не мати перевірок на isInterrupted, а також перехоплювати за допомогою try…catch(Exception e) всі винятки, що виникли.
Ніхто не гарантує, що потік можна зупинити. Він може зупинитися лише сам.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ