Eu tenho a classe principal Java, na classe, inicio um novo thread, no principal, ele aguarda até que o thread morra. Em algum momento, lanço uma exceção de tempo de execução do encadeamento, mas não consigo capturar a exceção lançada no encadeamento na classe principal.
Aqui está o código:
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)
{
}
}
}
Alguém sabe por que?
java
multithreading
NARU
fonte
fonte
Isso ocorre porque as exceções são locais em um encadeamento e o encadeamento principal não vê o
run
método. Sugiro que você leia mais sobre como o encadeamento funciona, mas para resumir rapidamente: sua chamada parastart
iniciar um encadeamento diferente, totalmente não relacionado ao seu encadeamento principal. A chamadajoin
simplesmente espera que isso seja feito. Uma exceção lançada em um encadeamento e nunca capturada o encerra, e é por isso quejoin
retorna ao seu encadeamento principal, mas a exceção em si é perdida.Se você deseja conhecer essas exceções não detectadas, tente o seguinte:
Mais informações sobre o tratamento de exceções não capturadas podem ser encontradas aqui .
fonte
Thread.setDefaultUncaughtExceptionHandler()
também captura exceções no thread "main"Isso explica a transição de estado dos encadeamentos, dependendo da ocorrência ou não de uma exceção:
Fonte: http://www-public.imtbs-tsp.eu/~gibson/Teaching/CSC7322/L8-ExceptionsAndThreads.pdf
fonte
Provavelmente;
No entanto, vamos supor que você precise manipular uma exceção de um thread filho outro. Eu usaria um ExecutorService como este:
impressões
fonte
future.get()
espera ou bloqueia até que o thread termine a execução?Por favor, dê uma olhada no Thread.UncaughtExceptionHandler
Melhor (alternativa) é usar Callable e Future para obter o mesmo resultado ...
fonte
Use em
Callable
vez de Thread, então você pode chamar oFuture#get()
que lança qualquer exceção lançada pelo Callable.fonte
Callable.call
é agrupada emExcecutionException
e sua causa deve ser avaliada.No momento, você está capturando apenas
RuntimeException
uma subclasse deException
. Mas seu aplicativo pode lançar outras subclasses de exceção . Capturar genéricoException
, além deRuntimeException
Como muitas coisas foram alteradas na frente do Threading, use a API java avançada.
Prefira a API avançada java.util.concurrent para multi-threading como
ExecutorService
ouThreadPoolExecutor
.Você pode personalizar seu ThreadPoolExecutor para manipular exceções.
Exemplo da página de documentação do oracle:
Sobrepor
Código de exemplo:
Uso:
Eu adicionei um construtor sobre o código acima como:
Você pode alterar esse construtor para atender aos seus requisitos no número de threads.
fonte
Eu enfrentei o mesmo problema ... pouco trabalho (apenas para implementação não objetos anônimos) ... podemos declarar o objeto de exceção no nível de classe como nulo ... e inicializá-lo dentro do bloco catch para o método run ... se houver Foi um erro no método run, esta variável não será nula. Podemos fazer uma verificação nula para essa variável em particular e, se não for nula, houve uma exceção na execução do encadeamento.
chame checkForException () após join ()
fonte
Você brincou com os métodos setDefaultUncaughtExceptionHandler () e similares da classe Thread? Na API: "Ao definir o manipulador de exceção não capturado padrão, um aplicativo pode alterar a maneira como as exceções não capturadas são tratadas (como registrar em um dispositivo ou arquivo específico) para os segmentos que já aceitariam qualquer comportamento" padrão ". sistema fornecido. "
Você pode encontrar a resposta para o seu problema lá ... boa sorte! :-)
fonte
Também do Java 8, você pode escrever a resposta de Dan Cruz como:
fonte
AtomicReference também é uma solução para passar o erro ao thread principal. É a mesma abordagem que a de Dan Cruz.
A única mudança é que, em vez de criar uma variável volátil, você pode usar o AtomicReference, que fez a mesma coisa nos bastidores.
fonte
É quase sempre errado estender
Thread
. Não posso afirmar isso com força suficiente.Regra multithreading # 1: a extensão
Thread
está incorreta. *Se você implementar
Runnable
, verá o seu comportamento esperado.produz;
* a menos que você queira alterar a maneira como seu aplicativo usa threads, o que em 99,9% dos casos você não usa. Se você pensa que está em 0,1% dos casos, consulte a regra nº 1.
fonte
Se você implementar Thread.UncaughtExceptionHandler na classe que inicia os Threads, poderá definir e, em seguida, repetir novamente a exceção:
O que causa a seguinte saída:
fonte
Manipulação de exceções no Thread: Por padrão, o método run () não lança nenhuma exceção; portanto, todas as exceções verificadas dentro do método run devem ser capturadas e manipuladas apenas nele e, para exceções de tempo de execução, podemos usar UncaughtExceptionHandler. UncaughtExceptionHandler é uma interface fornecida pelo Java para manipular exceções em um método de execução de Thread. Portanto, podemos implementar essa interface e retornar nossa classe de implementação ao objeto Thread usando o método setUncaughtExceptionHandler (). Mas esse manipulador deve ser definido antes de chamarmos start () na banda de rodagem.
se não definirmos uncaughtExceptionHandler, o ThreadGroup Threads atuará como um manipulador.
Boa explicação dada em http://coder2design.com/thread-creation/#exceptions
fonte
Minha solução com o RxJava:
fonte
Para aqueles que precisam parar todos os Threads em execução e executar novamente todos eles quando qualquer um deles estiver parado em uma exceção:
Resumindo :
Você tem uma função principal que cria vários encadeamentos, cada um deles com UncaughtExceptionHandler, que é acionado por qualquer exceção dentro de um encadeamento. Você adiciona todos os threads a uma lista. Se um UncaughtExceptionHandler for acionado, ele percorrerá a Lista, parará todos os Threads e reiniciará a função principal recreação de todo o Thread.
fonte
Você não pode fazer isso, pois isso realmente não faz sentido. Se você não tivesse chamado
t.join()
, o encadeamento principal poderia estar em qualquer lugar no código quando ot
encadeamento lança uma exceção.fonte