2010-12-20 11 views
15

Nel thread Java, il metodo 'run' non può generare un''eccezione controllata '. L'ho trovato nel libro Core Java (vol. 1). Qualcuno può spiegare il ragionamento dietro di esso?Thread Java: il metodo Run non può generare un'eccezione controllata

+4

Dove sarebbe l'eccezione andare? Da allora il thread che ha generato il nuovo thread è stato spostato. Quindi, in che modo il nuovo thread "invia" l'eccezione al thread di origine che ha sparato e dimenticato il thread? – chaotic3quilibrium

risposta

16

Qualcuno può spiegare il ragionamento dietro di esso?

Sì, perché qualsiasi eccezione che si introduce nel metodo run verrà ignorata con attenzione da JVM. Quindi, lanciandolo probabilmente c'è un errore (a meno che tu non abbia un gestore di eccezioni specifico per il thread, vedi su the docs). Nessun motivo per incitare un comportamento potenzialmente errato.

Oppure, con un esempio.

class MyThread extends Thread { 
    public void run() { 
     throw new RuntimeException(); 
    } 
} 

... 

new MyThread().start(); 
// here thread dies silently with no visible effects at all 

modificare

Perché non è possibile il filo genitore 'catturare' l'eccezione dal thread spawn 'bambino'?

@ chaotic3quilibrium ha già osservato nel suo commento perché non: perché discussione genitore è probabilmente andato avanti già.

new MyThread().start(); // launch thread and forget 

// 1000 lines of code further... 
i = i + 1; // would you like exception from child thread to be propagated here? 
+0

Puoi spiegare il ragionamento alla base della JVM ignorando attentamente le eccezioni in 'run'? –

+0

@Martinho Che altro può fare? L'opzione Suicidio suona ancora peggio: non vorrebbe che l'intera applicazione si blocchi a causa di un thread. –

+4

Silenzioso ignorare è forse fuorviante. L'eccezione sarà gestito da UncaughtExceptionHandler del thread, l'implementazione di default dei quali permette di scaricare le stacktrace a System.err prima di uccidere il thread. Per quanto riguarda il perché: come fa la VM sapere invece cosa fare? – meriton

0

throws dichiarazioni fanno parte della firma dei metodi. Per consentire eccezioni controllate per Runnable#run, si è dovuto dichiararle nell'interfaccia Runnable e si è dovuto a try/catch ogni volta che si avvia una discussione.

Quindi di nuovo, di solito non chiamiamo il metodo run, lo implementiamo solo. Abbiamo start() una discussione e quindi, in qualche modo, viene chiamato il metodo run.

Ma la ragione più ovvia: Quando iniziamo le discussioni, che di solito non vogliamo aspettare fino a quando il metodo run termina solo per intercettare le eccezioni in questo modo:

try { 
    new Worker().start(); // now wait until run has finished 
} catch (SomeThreadException oops) { 
    // handle checked exception 
} 
0

La ragione è che un'eccezione è gettata all'indietro al chiamante. Il metodo Caller of run() non è il tuo codice. È il Thred stesso. Quindi, anche se run() genera un'eccezione, il programma non riesce a prenderlo.

Si dovrebbe inserire il risultato dell'esecuzione del thread su una variabile di livello di classe e quindi leggerlo da lì. In alternativa, usa la nuova API: esecutori e interfaccia Callable che dichiara il metodo call() che restituisce il risultato futuro dell'esecuzione del thread.

7

Cosa catturerebbe l'eccezione e la gestirà? Supponiamo che il metodo run possa generare un'eccezione controllata. Poi si potrebbe scrivere codice come questo:

Thread myThread = new Thread(aRunnable); 
try{ 
    myThread.start(); 
} 
catch(Exception e){ 
    e.printStackTrace(); 
} 
//do other stuff 

ma una volta che si chiama myThread.start, il nuovo thread viene avviato in background e il thread corrente continua ed esce il try-catch e fa altre cose. Quindi se myThread ha lanciato un'eccezione in seguito, non puoi prenderlo!

Quello che devi fare è gestire l'eccezione nel metodo run e quindi probabilmente avere un modo di notificare a un altro oggetto che questo thread ha avuto esito negativo.

0

La soluzione più evidente per le risposte precedenti è che se si lancia un'eccezione controllata, non si sta implementando correttamente run() come specificato nell'interfaccia eseguibile.

Non sarà anche compilare:

run() in TestClass cannot implement run() in java.lang.Runnable; 
overridden method does not throw java.lang.Exception 
1

Supponiamo thread A avvia filo B. Quindi filo B genera un'eccezione. Potresti pensare che sarebbe bello per il thread A catturarlo. Ma dove? Per il momento in cui il thread B presenta l'eccezione, chissà cosa sta facendo il thread A? Per fare un esempio banale, supponiamo di avere questo codice in thread A:

try 
{ 
    threadB=new PurgeAbandonedCarts(); 
    threadB.start(); 
} 
catch (NullPointerException panic) 
{ 
    ... handle errors purging abandoned carts ... 
} 
try 
{ 
    processNewOrders(); 
} 
catch (NullPointerException panic) 
{ 
    ... handle problems in new orders ... 
} 
finally 
{ 
    ... clean up ... 
} 

Così abbiamo avviamento thread B per eliminare carrelli abbandonati. Una volta avviato, passiamo all'elaborazione di nuovi ordini. Quindi il thread B genera un'eccezione di puntatore nullo. Dovrebbe essere catturato dal blocco catch associato al thread B o da quello associato all'elaborazione di nuovi ordini?

Se va alla nuova ordini di cattura, è probabile che il codice qui non ha nulla a che fare con la pulizia problemi con filo B. Questo non può essere la risposta giusta.

Se si dice quello associato al thread B, ciò significa che durante l'elaborazione di nuovi ordini, il controllo potrebbe essere improvvisamente strappato e inviato per provare il blocco catch del thread B. Ma allora cosa è successo all'elaborazione di nuovi ordini? Ci fermiamo nel mezzo? Non abbiamo nemmeno colpito il blocco finale? E quando abbiamo finito, continuiamo a eseguire e ricominciamo a elaborare nuovamente i nuovi ordini? Elaboriamo gli ordini due volte? Anche questa non può essere la risposta giusta.

Quindi, non c'è nessun posto dove andare se correre genera un'eccezione. L'unica cosa logica da fare è fare in modo che il metodo run rilevi eventuali eccezioni generate da sé e gestirle all'interno del nuovo thread.

Problemi correlati