Решил задачу поставив setDefaultUncaughtExceptionHandler(handler);
Но если честно не понял ничего ибо подглядел решение в комментариях. Кто может объяснить построчно или максимально подробно что делает программа?
Эмир Смагулов
17 уровень
Непонимание.
Обсуждается
Комментарии (23)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
StepkaInspiration
4 марта, 18:05
Ребят, я понял, что надо перенести строчку с установкой хэндлера на нить из конструктора в run(), но не понял одну деталь: почему без выделенных слов (Thread.currentThread()) хэндлер для threadA и ThreadB устанавливаться не будет? Это же они проходят по этой строчке и он, казалось бы, должен работать для них просто в виде "setUncaughtExceptionHandler(handler);"
Надеюсь, что достаточно понятно изложил вопрос
0
Ivasishinav
1 июля 2022, 17:16
Я понял так: =)
у программы в данном случае 4 нити, а именно:
1) что создается и запускается в public static void main
2) что создается при создании TestedThread commonThread и запускается в конструкторе TestedThread
3) threadA, что создается в первой нити и запускается в ней же
4) threadB, что создается в первой нити и запускается в ней же
Первая нить:
создала и запустила 3 оставшиеся нити, а затем принудительно поставила флаг остановки на нити threadA и threadB, после успешно завершилась.
Вторая нить (commonThread):
Установила себе в конструкторе отловщика setUncaughtExceptionHandler(handler);
запустилась, проспала 3 секунды и успешно завершилась, т.к. ее никто принудительно не пытался "выключить"
Третяя нить (threadA):
была создана на основе commonThread, но setUncaughtExceptionHandler(handler) в конструкторе TestedThread на нее не распространился, т.к. она создана на основе уже существующего объекта и конструктор отработал всего 1 раз (при создании commonThread)
Т.к. конструктор TestedThread на нее не распространился, то и запустить нам пришлось ее в первой нити строкой threadA.start();
она заснула на 3 секунды
но в первой нити ее принудительно остановили, вызвав тем самым код из catch (InterruptedException e), а он в свою очередь пробросил исключение new RuntimeException;
которое нам ловить было нечем, т.к. настройки setUncaughtExceptionHandler(handler) в этой нити нет.
Четвертая нить (threadB)
Полностью аналогична третье.
Итого, чтобы поставить настройку отлавливания setUncaughtExceptionHandler(handler) мы можем:
- написать в методе run класса TestedThread
Thread.currentThread().setUncaughtExceptionHandler(handler);
таким образом 2,3,4 нити при старте поставят себе настройку "отлавливателя"
- после создания или старта (но обязательно до остановки) прописать каждой нити
threadA.setUncaughtExceptionHandler(handler);
threadB.setUncaughtExceptionHandler(handler);
+6
Ivasishinav
1 июля 2022, 17:15
- в конструкторе TestedThread прописать дефолтное значение для всех нитей путем:
Thread.setDefaultUncaughtExceptionHandler(handler);
+1
Zakir T
31 мая 2021, 01:30
https://javatutor.net/articles/catching-uncaught-exceptions
->
Существует три способа установки обработчика необрабатываемых ошибок. Первое, вы можете вызвать метод setUncaughtExceptionHandler() класса Thread.. Его вызов позволяет настроить поведение обработчика для выбранного потока. Второе, вы можете создать объект ThreadGroup и изменять поведение всех потоков в группе переопределив метод uncaughtException(). Третье, вы можете установить поведение по умолчанию для всех потоков вызвав статический метод setDefaultUncaughtExceptionHandler() класса Thread.
Методы setUncaughtExceptionHandler() и setDefaultUncaughtExceptionHandler() класса Thread в качестве аргумента принимает реализацию интерфейса UncaughtExceptionHandler. Данный интерфейс является внутренним интерфейсом класса Thread, таким образом, его полное имя будет Thread.UncaughtExceptionHandler. В данном интерфейсе определен один метод:
+1
Павел оператор в ОАО "Мозырский НПЗ"
12 ноября 2020, 19:36
Просмотрел комментарии и судя по уровням людей их писавшим, понять решение самостоятельно под силу ученикам с уровнем не ниже 30.
+10
Сергей
6 ноября 2018, 16:03
Для класса TestedThread создан конструктор в котором выполняется установка setUncaughtExceptionHandler(handler) и, может показаться, что этого достаточно. Но далее мы создаем две нити threadA и threadB, передавая им в качестве параметра объект класса commonThread. Который при передаче сужается до объекта Runnable(смотря аргументы конструктора Thread). Таким образом информация об необходимом обработчике не поступает в конструктор нитей. Для того чтобы всетаки установить обработчик, после создания нитей надо явно указать для них обработчики строками threadA.setUncaughtExceptionHandler(handler); и threadB.setUncaughtExceptionHandler(handler);
+135
Max
1 марта 2020, 09:11
Спасибо, ваш комментарий навел на правильные мысли.
Только в данном случае происходит не сужение, а расширение типа (Runnable стоит на вершине иерархии наследования).
Также замечу, что информация об обработчике не поступает в конструктор нитей не по причине расширения типа, а лишь по той причине, что все три объекта никак между собой не связаны в плане конфигурирования/инициализации - это три отдельные нити. А значит нужно либо конфигурировать их все вместе (setDefaultExceptionHandler, причем в правильном месте в коде, а не в конструкторе одной отдельной нити), либо каждую нить в отдельности (setExceptionHandler).
Также обратите внимание, что передавая Runnable в конструктор Thread, вы передаете новой нити реализацию метода run() уже существующего Runnable-объекта. Это означает, что в новую нить будет подставлена существующая реализация метода run() из объекта-аргумента. Конструктор объекта-аргумента отрабатывает только в момент создания нити данного типа (т.е. только один раз при создании TestedThread(handler)).
Таким образом, при создании нити на основе существующего Runnable-объекта, конструктор этого объекта не исполняется, а исполняется конструктор в классе Thread. Передача Runnable-аргумента нужна только для неявного определения метода run() в создаваемом объекте.
В оригинальной версии данной задачи (т.е. той, которая поставляется нам для решения) изначально сконфигурирована только одна нить - первая (TestedThread), которая на результат никак не влияет (именно поэтому из конструктора данной нити можно вообще удалить setUncaughtExceptionHandler(handler), он для решения вообще не нужен, т.к. нить не прерывается и успешно завершается сама без рейза каким-либо unchecked exceptions).
Итого, в задаче три нити, нам нужно для решения сконфигурировать две последние (threadA, threadB). Причем конфигурирование должно быть выполнено до запуска нити, а не после. Варианты как это сделать я описал. Дерзайте)
+178
Елена
3 марта 2020, 10:44
Спасибо! Немного смутило то, что в лекциях была фраза (https://javarush.com/quests/lectures/questcore.level06.lecture02)
"— Это решение красивее.
— Да, но у него есть минусы:
1) Вам может понадобиться запустить несколько нитей на основе одного единственного объекта, как это сделано в «примере с Наташей».
"
А получается в данной задаче мы как раз и делаем это, создаем три нити на основе одного объекта, используя в качестве аргумента объект класса, который наследует Thread, а не имплементит Runnable.
+1
Елена
3 марта 2020, 10:49
"Также обратите внимание, что передавая Runnable в конструктор Thread, вы передаете новой нити реализацию метода run() уже существующего Runnable-объекта. Это означает, что в новую нить будет подставлена существующая реализация метода run() из объекта-аргумента."
И еще вопр на понимание общее: верно ли я понимаю, что если бы а методе run было что-то типа this.count ++ (допустим есть такое поле), то нам обязательно надо было бы синхронизировать этот кусок кода по this, так как все три нити выполняются на основе одного объекта?
+2
Max
3 марта 2020, 12:17
Лучше бы, конечно, код видеть, чтобы точно ответить. Но исходя из текста, да - синхронизация нужна. Также операторы инкремента/декремента не являются атомарными (считываем, прибавляем/убавляем, записываем).
+1
Максим Сергеевич
7 апреля 2020, 18:32
Может быть я не очень правильно Вас понял, но, конструктор вполне выполняется и все работает, если поместить непосредственно в конструктор setDefaultUncaughtExceptionHandler(handler), не вызывая setUncaughtExceptionHandler(handler) непосредственно у каждой нити.
А в целом за объяснение спасибо.
+5
Михаил
23 апреля 2020, 18:08
первая (TestedThread), которая на результат никак не влияет (именно поэтому из конструктора данной нити можно вообще удалить setUncaughtExceptionHandler(handler), он для решения вообще не нужен, т.к. нить не прерывается и успешно завершается сама без рейза каким-либо unchecked exceptions).
Объясните пожалуйста, почему первая нить успешно завершается?
0
happyjun
21 мая 2020, 17:17
потому что нет строчки :
commonThread.interrupt();
и она проспав 3 секунды успешно сама завершается без *Exception*-ов, и соответственно без вызова метода uncaughtException
+1
Алексей Чумаков
28 мая 2020, 14:53
Потому что у нее не вызывается метод interrupt(); следовательно она не ловит исключения Interrupted exception
+1
Алексей Чумаков
28 мая 2020, 14:54
Как тогда setDefaultUncaughtExceptionHandler(handler); устанавливает значения всем нитям, если новая нить создаётся, из интерфейса Runnable?
Для тех кого мучает этот вопрос я все-таки понял простую вещь default метод статический)
+1
Юрий
25 июня 2020, 11:52
ничего не понял из вышесказанного,наверное тупой))
+8
Юрий
25 июня 2020, 11:55
хотя этот пример что-то более менее прояснил,но все равно сижу уже два часа пытаюсь вникнуть ))
0
Алексей Чумаков
26 июня 2020, 09:26
setDefaultUncaughtExceptionHandler устанавливает значение для статической переменной, которая будет хранить состояние для всех объектов. т.е. у любой вновь созданной нити она уже будет инициализирована нашим значением по умолчанию. Если в этом вопрос.
+4
Юрий
26 июня 2020, 15:56
да, это я понял,так как метод статический. Вопроса как такового нет, но пока сложно воспринять,видимо рано пришел)
+1
Тарас
22 августа 2020, 21:40
Не ты один такой )
+1
Sergey April
2 мая 2021, 10:23
Дай бог тебе здоровья милый человек! После 20 раза прочтения, я наконец-то понял!!! СПАСИБО!
0
Жора Нет
15 мая 2021, 18:53
Согласен. Я тоже
0
Greatsky future developer в future developer
7 января 2022, 19:51
Давайте подытожим передовая аргумент Runnable-объекта в конструктор Thread - будет использован переопределенный метод run () передаваемого Runnable-объекта, setUncaughtExceptionHandler(handler) в конструкторе TestedThread в данной задаче не нужен. но если написать в main () commonThread.interrupt(); то тоже нужен, если захотел по умолчанию делать для всех Thread - по аналогии с задачей должен написать
Причем идея сразу предложила использовать лямду (до чего умные разработчики программы)
+1