JavaRush /Курсы /Java Multithreading /Стек вызовов и перехват ошибок

Стек вызовов и перехват ошибок

Java Multithreading
5 уровень , 8 лекция
Открыта

— Привет, Амиго!

Хочу рассказать тебе о маленькой, но интересной вещи.

— Я слушаю. Люблю интересные и маленькие вещи.

Так вот, ты знаешь, что у каждого объекта Thread есть метод run(). И что можно запустить его на выполнение в отдельной нити с помощью метода start().

— Да, конечно.

— А вот представь теперь ситуацию – ты запускаешь нить, чтобы она выполнила нужную тебе работу, а у нее внутри возникает Exception и она завершает работу, так и не выполнив того, что надо. Тебе бы надо как-то узнать об этой ошибке?

— Согласен. А что, как-то можно перехватить исключение, которое возникло в другой запущенной нити. Неужели даже это есть в Java?

— Обижаешь. Еще как есть.

Разработчики Java придумали специальный интерфейс UncaughtExceptionHandler. Вот как можно перехватить и обработать исключение в другой нити, если она не перехватила его сама:

Пример
public class DownloadManager
{
 public static void main(String[] args)
 {
   Thread thread = new DownloadThread();
   thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { } });

 thread.start();
}

У объекта типа Thread есть специальный метод – setUncaughtExceptionHandler. В него нужно передать объект, который реализует интерфейс Thread.UncaughtExceptionHandler. У этого интерфейса есть всего один метод uncaughtException(Thread t, Throwable e). Именно этот метод будет вызван у переданного объекта, если внутри метода run возникнет исключение, которое не будет захвачено.

В приведенном мной примере, я просто объявляю анонимный внутренний класс (выделено красным), реализующий интерфейс Thread.UncaughtExceptionHandler. И переопределяю в нем метод uncaughtException(Thread t, Throwable e).

Как видно из параметров метода, в него будут переданы два параметра – ссылка на Thread, в котором возникло исключение, и само исключение – Throwable e.

— А зачем нужна ссылка на Thread — переменная t? Мы же знаем, в какой поток устанавливаем объект типа Thread.UncaughtExceptionHandler?

— А это сделано для того, чтобы ты мог написать универсальный обработчик таких ситуаций – создать один единственный объект и передавать его десяткам различных потоков. Тогда внутри метода uncaughtException(Thread t, Throwable e) у тебя всегда будет ссылка на нить, где возникло исключение.

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

— Я тебе верю. Ты еще ни разу не ошибалась.

Комментарии (104)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Marat Safiianov Уровень 39
23 июня 2025
1. Проблема: необработанные исключения в потоках Если в методе run() выбрасывается RuntimeException или Error, и ты его не перехватил внутри потока, он приведёт к аварийному завершению потока без уведомления остальной программы. 🛠 2. Специальный инструмент — UncaughtExceptionHandler Java позволяет: Назначить обработчик на конкретный поток или установить обработчик по умолчанию для всех потоков Он реализует интерфейс: interface Thread.UncaughtExceptionHandler { void uncaughtException(Thread t, Throwable e); } Метод uncaughtException получает: Thread t — поток, в котором произошло исключение Throwable e — само исключение 🧩 3. Как использовать Для одного потока: Thread thread = new DownloadThread(); thread.setUncaughtExceptionHandler((t, e) -> { System.out.println("Поймали в " + t.getName() + ": " + e); }); thread.start(); Если DownloadThread выкинет, например, ArithmeticException, то твой лямбда-обработчик выполнится и сможет вывести информацию, залогировать её, отправить на сервер 📡. Для всех потоков сразу: Thread.setDefaultUncaughtExceptionHandler((t, e) -> { // третируем все необработанные исключения }); Этот код сработает, даже если обработчик не установлен вручную для каждого потока . 🎯 Зачем это нужно Для устойчивости и надёжности приложений, особенно многопоточных Позволяет: Логировать ошибки Чисто останавливать связанные процессы Информировать пользователя или систему мониторинга
Long_byte Уровень 16
5 июня 2024
перехвачивает исключение другой нити который сам не обработал это как понять
Бромгексин Уровень 38
10 августа 2024
перехват unChecked исключений
Nikolai Уровень 39
23 мая 2024
uncaughtHandler нужны для того, чтобы ловить unchecked-исключения (RuntimeException и наследники) и их в последующем обрабатывать.

thread.setUncaughtExceptionHandler((t, e) -> {

*
Ваша обработка исключений. К примеру System.out.println("Исключение отловлено"); 
//данная строка выводит данное сообщение, если в вашем потоке выкидывается любое unchecked-исключение RuntimeException (и наследники)
*
});
Rolik Уровень 41
18 апреля 2023
Кто нибудь объясните, чем отличаются сеттеры: setUncaughtExceptionHandler от setDefaultUncaughtExceptionHandler ?
hidden #3100116 Уровень 37
4 мая 2023
setUncaughtExceptionHandler используется для установки обработчика для конкретного потока, а setDefaultUncaughtExceptionHandler - статический метод класса Thread, нужен для установки обработчика по умолчанию для всех потоков
Михаил Уровень 32
13 ноября 2022

public interface MyUncaughtExceptionHandler extends Thread.UncaughtExceptionHandler {
    @Override
    void uncaughtException(Thread t, Throwable e);
}

public class DownloadThread extends Thread{
    private char ch = 'a';

    @Override
    public void run() {
        char i = ch;
        while (isAlive()){
            System.out.println(ch++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (ch == (i+10)) ch = (char) (ch/0);
        }
    }
}

public class UncaughtExceptionDemo {
    public static void main(String[] args) {
        Thread thread = new DownloadThread();
        thread.setUncaughtExceptionHandler((MyUncaughtExceptionHandler) (t, e) -> System.out.println("Хуюшки!"));
        thread.start();
    }
}
Daniel Уровень 51
31 января 2023
Великолепно! Снимаю шляпу.
very junior java developer Уровень 51
21 мая 2023
Только не ясно, зачем тут создавать очередной интерфейс MyUncaughtExceptionHandler с 1м методом. без него результат идентичный :

public class UncaughtExceptionHandlerDemo {
    public static void main(String[] args) {
        Thread thread = new DownloadThread();
        thread.setUncaughtExceptionHandler((t, e) -> System.out.println("Хуюшки!"));
        thread.start();
    }
}
otreyo Уровень 38
13 августа 2022
это какой то особый талант. писать максимально невнятно и непонятно, зато с диалогами для детей из детского сада или для альтернативно одаренных
KirilX Уровень 51
22 июля 2022
Задача опередила теорию.
defezis Уровень 35
15 апреля 2022
Да, начиная с первых уровней, это происходит. Об это с благодарностью упоминают те, кто прошёл весь путь. Это часть обучения. Так эффективнее. Осилили задачу - отлично. Когда доберетесь до лекции, где всё объясняют, надёжно закрепите знания. Не осилили - после вернетесь. Вернее, надо вернуться. Метод Колба Как быстро изучать новое?
Oleg Khilko Уровень 51
8 июля 2022
не, братан, гораздо интереснее нарыть в гугле UncaughtExceptionHandler и найти закрытую лекцию, потом в комментах найти коммент Зеппа что нужно это страницу открыть в режиме инкогнито, прочитать раздел - нихера не понять и вернуться в задачу разбираться с уже "обретенными знаниями"))
16 июля 2022
Да, согласен эмпирический путь или метод тыка самый действенный!
Андрей Уровень 42
31 марта 2023
спасибо за ссылки.
БелК в труселях Уровень 35
24 февраля 2022
Бред. Я голову ломал в помощь написал а тут написано. Вот что писать?
Sergey Kornilov Уровень 39
22 января 2022
Ранее решили задачу по данной лекции, и вот она "очень своевременна".