2010-12-20 9 views
15

En el subproceso de Java, el método 'ejecutar' no puede arrojar una 'excepción marcada'. Me encontré con esto en el libro Core Java (vol 1). ¿Alguien puede explicar el razonamiento detrás de esto?Subproceso de Java: el método de ejecución no puede lanzar la excepción comprobada

+4

¿Dónde iría la excepción? El hilo que engendró el nuevo hilo se ha movido desde entonces. Entonces, ¿cómo podría el nuevo hilo "enviar" la excepción al hilo de origen que había disparado y olvidado dicho hilo? – chaotic3quilibrium

Respuesta

16

¿Puede alguien explicar el razonamiento detrás de esto?

Sí, porque cualquier excepción que arroje en el método run será cuidadosamente ignorada por JVM. Por lo tanto, arrojarlo allí es probablemente un error (a menos que tengas un controlador de excepción específico para el hilo, mira the docs al respecto). No hay razón para incitar un comportamiento potencialmente erróneo.

O, con un ejemplo.

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

... 

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

edición

Por qué no puede el hilo padre 'captura' la excepción de la hebra generada 'niño'?

@ chaotic3quilibrium ya se ha señalado en su comentario por qué no: porque el hilo de los padres probablemente ha pasado ya.

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

¿Puedes explicar el razonamiento detrás de la JVM ignorando cuidadosamente las excepciones en 'ejecutar'? –

+0

@Martinho ¿Qué más puede hacer? La opción de suicidio suena aún peor: no querría que toda la aplicación se bloquee debido a un hilo. –

+4

ignorar silenciosamente es tal vez engañoso. La excepción será manejada por el UncaughtExceptionHandler del subproceso, cuya implementación predeterminada arrojará el stacktrace a System.err antes de matar el subproceso. En cuanto a por qué: ¿Cómo sabría la VM qué hacer? – meriton

0

throws declaraciones forman parte de la firma de métodos. Para permitir excepciones marcadas para Runnable#run, había que declararlas en la interfaz Runnable y tener que try/catch cada vez que iniciamos un hilo.

Por otra parte, generalmente no llamamos al método run, simplemente lo implementamos. Nos start() un hilo y luego, de alguna manera, se llama al método run.

Pero la razón más obvia: Cuando empezamos las discusiones, por lo general no queremos esperar hasta que el método run termina sólo para capturar las excepciones de esta manera:

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

La razón es que la excepción es lanzada hacia atrás a la persona que llama. El método Caller of run() no es tu código. Es el Thred en sí mismo. Entonces, incluso si run() arroja una excepción, el programa no puede atraparlo.

Debería poner el resultado de la ejecución del hilo en una variable de nivel de clase y luego leerla desde allí. O, alternativamente, use una nueva API: ejecutores y la interfaz Invocable que declara el método call() que devuelve el resultado futuro de la ejecución de la secuencia.

7

¿Qué atraparía la excepción y la manejaría? Supongamos que el método de ejecución arroja una excepción marcada. Posteriormente, se podría escribir código como este:

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

pero una vez que se llama a myThread.start, el nuevo hilo se inicia en el fondo y el hilo de corriente continua y sale de la try-catch y hace otras cosas. Entonces, si myThread arrojó una excepción más adelante, ¡no puede atraparlo!

Lo que debe hacer es ocuparse de la excepción dentro del método run y luego probablemente tenga una forma de notificar a otro objeto que este subproceso falló.

0

La solución más obvia a las respuestas anteriores es que si lanza una excepción marcada, no está implementando correctamente run() como se especifica en la interfaz ejecutable.

No será incluso compilar:

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

Supongamos que el hilo se pone en marcha un hilo B. A continuación, el hilo B se produce una excepción. Podrías pensar que sería bueno para el hilo A atraparlo. ¿Pero donde? Para cuando el hilo B lanza la excepción, ¿quién sabe qué hilo A está haciendo? Para tomar un ejemplo trivial, supongamos que tenemos este código en un hilo:

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 ... 
} 

por lo que empezamos hilo B para purgar los carros abandonados. Una vez que se inicia, pasamos al procesamiento de nuevos pedidos. Luego, el hilo B arroja una excepción de puntero nulo. ¿Debería atraparlo el bloque catch asociado con el thread B, o el asociado con el procesamiento de nuevos pedidos?

Si se trata de la captura de nuevas órdenes, es probable que cualquier código aquí no tenga nada que ver con la limpieza de problemas con el subproceso B. Esa no puede ser la respuesta correcta.

Si dice el asociado con el hilo B, significa que durante el procesamiento de nuevos pedidos, el control podría ser retirado y enviado de vuelta para probar el bloque catch B del hilo. Pero, ¿qué pasó con el procesamiento de nuevas órdenes? ¿Simplemente nos detenemos en el medio? ¿Ni siquiera golpeamos el bloque final? Y cuando terminemos, ¿seguiremos ejecutando y luego volveremos a procesar nuevas órdenes? ¿Procesamos los pedidos dos veces? Esta tampoco puede ser la respuesta correcta.

Por lo tanto, no hay ningún lugar a donde ir si ejecuta arroja una excepción. Lo único lógico que hay que hacer es hacer que el método run capture todas las excepciones lanzadas y manejarlas dentro del nuevo hilo.

Cuestiones relacionadas