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

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

Открыта

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

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

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

Так вот, ты знаешь, что у каждого объекта 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) у тебя всегда будет ссылка на нить, где возникло исключение.

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

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

Комментарии (108)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Максим Li Backend Developer
26 ноября 2025, 02:03
JavaRusher853
Уровень 36
21 октября 2025, 08:41
Вау! Ничего не понятно.
29 июля 2025, 12:18
# UncaughtExceptionHandler
1. **Назначение**:
   - Перехват исключений, не пойманных в потоке.
   - Предотвращение "молчаливого" падения потока.

2. **Установка**:
   - `Thread.setDefaultUncaughtExceptionHandler()` — глобально.
   - `thread.setUncaughtExceptionHandler()` — для конкретного потока.

3. **Приоритет**:
   Поток → Группа потоков → Глобальный обработчик.

4. **Использование**:
   - Логирование, уведомления, перезапуск потоков.
   - Грациозное завершение приложения.

5. **Пул потоков**:
   - Обработчик по умолчанию не применяется!
   - Решение: установка через `ThreadFactory` или переопределение `afterExecute()`.
Ioanna Polyak
Уровень 44
9 июля 2025, 12:52
Хммм...
Marat Safiianov
Уровень 41
23 июня 2025, 18:28
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
Уровень 59
5 июня 2024, 08:33
перехвачивает исключение другой нити который сам не обработал это как понять
Бромгексин
Уровень 38
10 августа 2024, 11:51
перехват unChecked исключений
Nikolai Backend Developer
23 мая 2024, 06:55
uncaughtHandler нужны для того, чтобы ловить unchecked-исключения (RuntimeException и наследники) и их в последующем обрабатывать.
thread.setUncaughtExceptionHandler((t, e) -> {

*
Ваша обработка исключений. К примеру System.out.println("Исключение отловлено");
//данная строка выводит данное сообщение, если в вашем потоке выкидывается любое unchecked-исключение RuntimeException (и наследники)
*
});
Rolik
Уровень 41
18 апреля 2023, 15:58
Кто нибудь объясните, чем отличаются сеттеры: setUncaughtExceptionHandler от setDefaultUncaughtExceptionHandler ?
hidden #3100116
Уровень 37
4 мая 2023, 18:40
setUncaughtExceptionHandler используется для установки обработчика для конкретного потока, а setDefaultUncaughtExceptionHandler - статический метод класса Thread, нужен для установки обработчика по умолчанию для всех потоков
Михаил
Уровень 32
13 ноября 2022, 15:13
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();
    }
}
DanielCEO в BicycleInventionAcad
31 января 2023, 02:45
Великолепно! Снимаю шляпу.
21 мая 2023, 09:51
Только не ясно, зачем тут создавать очередной интерфейс 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, 03:51
это какой то особый талант. писать максимально невнятно и непонятно, зато с диалогами для детей из детского сада или для альтернативно одаренных