У меня есть основной класс Java, в классе я запускаю новый поток, в основном он ждет, пока поток не умрет. В какой-то момент я выбрасываю исключение времени выполнения из потока, но не могу поймать исключение, выброшенное из потока в основном классе.
Вот код:
public class Test extends Thread
{
public static void main(String[] args) throws InterruptedException
{
Test t = new Test();
try
{
t.start();
t.join();
}
catch(RuntimeException e)
{
System.out.println("** RuntimeException from main");
}
System.out.println("Main stoped");
}
@Override
public void run()
{
try
{
while(true)
{
System.out.println("** Started");
sleep(2000);
throw new RuntimeException("exception from thread");
}
}
catch (RuntimeException e)
{
System.out.println("** RuntimeException from thread");
throw e;
}
catch (InterruptedException e)
{
}
}
}
Кто-нибудь знает почему?
java
multithreading
Нара
источник
источник
Это потому, что исключения являются локальными для потока, а ваш основной поток фактически не видит
run
метод. Я предлагаю вам прочитать больше о том, как работает многопоточность, но чтобы быстро подвести итог: ваш вызовstart
запускает другой поток, совершенно не связанный с вашим основным потоком. Призывjoin
просто ждет, когда это будет сделано. Исключение, которое выдается в потоке и никогда не перехватывается, завершает его, поэтомуjoin
возвращается в ваш основной поток, но само исключение теряется.Если вы хотите знать об этих необработанных исключениях, вы можете попробовать это:
Более подробную информацию об обработке необработанных исключений можно найти здесь .
источник
Thread.setDefaultUncaughtExceptionHandler()
также перехватывает исключения в потоке "main"Это объясняет переход состояния потоков в зависимости от того, возникли исключения или нет:
Источник: http://www-public.imtbs-tsp.eu/~gibson/Teaching/CSC7322/L8-ExceptionsAndThreads.pdf
источник
Наверняка;
Однако предположим, что вам нужно обработать исключение из дочернего потока другого. Я хотел бы использовать ExecutorService, как это:
печать
источник
future.get()
ждет или не блокирует, пока поток не закончил выполнение?Пожалуйста, взгляните на Thread.UncaughtExceptionHandler
Лучший (альтернативный) способ - использовать Callable и Future, чтобы получить одинаковый результат ...
источник
Используйте
Callable
вместо Thread, тогда вы можете вызвать,Future#get()
который выбрасывает любое исключение, которое выбрасывает Callable.источник
Callable.call
обернуто вExcecutionException
и его причина должна быть оценена.В настоящее время вы ловите только
RuntimeException
подклассException
. Но ваше приложение может выдавать другие подклассы исключения . Поймать универсальныйException
в дополнение кRuntimeException
Так как многие вещи были изменены на фронте Threading, используйте расширенный API Java.
Предпочитаю предварительный API java.util.concurrent для многопоточности, например
ExecutorService
илиThreadPoolExecutor
.Вы можете настроить свой ThreadPoolExecutor для обработки исключений.
Пример со страницы документации оракула:
Override
Пример кода:
Использование:
Я добавил один конструктор поверх кода выше:
Вы можете изменить этот конструктор в соответствии с вашими требованиями по количеству потоков.
источник
Я столкнулся с той же проблемой ... немного обойти (только для реализации не анонимных объектов) ... мы можем объявить объект исключения уровня класса как нулевой ... затем инициализировать его внутри блока catch для метода run ... если есть была ошибка в методе run, эта переменная не будет иметь значение null .. тогда мы можем иметь нулевую проверку для этой конкретной переменной, и, если она не равна NULL, то возникла исключительная ситуация внутри выполнения потока.
вызовите checkForException () после join ()
источник
Играли ли вы с setDefaultUncaughtExceptionHandler () и схожими методами класса Thread? Из API: «Устанавливая обработчик необработанных исключений по умолчанию, приложение может изменить способ обработки необработанных исключений (например, запись на определенное устройство или файл) для тех потоков, которые уже приняли бы любое поведение« по умолчанию », Система обеспечена. "
Вы можете найти ответ на свой вопрос там ... удачи! :-)
источник
Также из Java 8 вы можете написать ответ Dan Cruz как:
источник
AtomicReference также является решением для передачи ошибки в основной поток. Это такой же подход, как у Дана Круза.
Единственное изменение состоит в том, что вместо создания изменчивой переменной вы можете использовать AtomicReference, который делал то же самое за кулисами.
источник
Это почти всегда неправильно расширять
Thread
. Я не могу утверждать это достаточно сильно.Правило многопоточности # 1: Расширение
Thread
неверно. *Если вы реализуете
Runnable
вместо этого вы увидите ожидаемое поведение.производит;
* если вы не хотите изменить способ, которым ваше приложение использует потоки, чего в 99,9% случаев нет. Если вы считаете, что находитесь в 0,1% случаев, см. Правило № 1.
источник
Если вы реализуете Thread.UncaughtExceptionHandler в классе, который запускает потоки, вы можете установить, а затем повторно вызвать исключение:
Что вызывает следующий вывод:
источник
Обработка исключений в потоке: по умолчанию метод run () не выдает никаких исключений, поэтому все проверенные исключения внутри метода run должны перехватываться и обрабатываться только там, а для исключений времени выполнения мы можем использовать UncaughtExceptionHandler. UncaughtExceptionHandler - это интерфейс, предоставляемый Java для обработки исключений в методе выполнения потока. Таким образом, мы можем реализовать этот интерфейс и вернуть наш реализующий класс обратно в объект Thread, используя метод setUncaughtExceptionHandler (). Но этот обработчик должен быть установлен до того, как мы вызовем start () на шаге.
если мы не установим uncaughtExceptionHandler, то ThreadGroup действует как обработчик.
Хорошее объяснение дано на http://coder2design.com/thread-creation/#exceptions
источник
Мое решение с RxJava:
источник
Для тех, кому необходимо остановить все запущенные потоки и перезапустить все, когда какой-либо из них остановлен в исключении:
Подводить итоги :
У вас есть основная функция, которая создает несколько потоков, каждый из которых имеет UncaughtExceptionHandler, который вызывается любым исключением внутри потока. Вы добавляете каждую тему в список. Если UncaughtExceptionHandler является триггером, он будет циклически проходить по списку, останавливать каждый поток и перезапускать основную функцию, воссоздающую весь поток.
источник
Вы не можете сделать это, так как это не имеет смысла. Если вы не вызывали,
t.join()
тогда ваш основной поток может быть где угодно в коде, когдаt
поток генерирует исключение.источник