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

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

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

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

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

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