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
Respuesta
¿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?
¿Puedes explicar el razonamiento detrás de la JVM ignorando cuidadosamente las excepciones en 'ejecutar'? –
@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. –
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
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
}
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.
¿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ó.
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
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.
- 1. excepción no comprobada que hubiera sido mejor como comprobada
- 2. Diferencia entre la excepción no comprobada o la excepción en tiempo de ejecución
- 3. java: no se puede volver a lanzar una excepción: no controlada tipo de excepción Excepción
- 4. ¿Lanzar una excepción sin detener la ejecución?
- 5. Comprobado frente a excepción no comprobada
- 6. ¿Puede Monitor.Enter lanzar una excepción?
- 7. Cómo lanzar una excepción cuando la firma de su método no permite lanzar Exception?
- 8. Java: ¿por qué no puedo lanzar una excepción en Comparator?
- 9. ¿Hay un buen método en C# para lanzar una excepción en un subproceso dado
- 10. Invocar un método de limpieza para el subproceso de usuario Java, cuando JVM detiene el subproceso
- 11. Obtiene el tiempo de ejecución de un subproceso Java
- 12. ¿Por qué la excepción de tiempo de ejecución es una excepción no marcada?
- 13. Lanzar Excepción genérica desalentado?
- 14. ¿Debe un método de recuperación devolver 'nulo' o lanzar una excepción cuando no puede producir el valor de retorno?
- 15. Lanzar manualmente una excepción
- 16. Lanzar una nueva excepción al lanzar una excepción antigua
- 17. Programe un ejecutable repetitivo de subproceso simple en java, pero omita la ejecución actual si la ejecución anterior no finaliza
- 18. Cómo lanzar una excepción marcada de un hilo de Java?
- 19. C# "Método no encontrado" excepción en el tiempo de ejecución sin uso de la reflexión
- 20. Diferencia entre llamar a sys.exit() y lanzar excepción
- 21. El método Image.FromStream() devuelve la excepción de argumento no válido
- 22. Lanzar una excepción no definida en la interfaz
- 23. Lanzar un shell IPython en la excepción
- 24. CSS3: pseudo-class no comprobada
- 25. Clojure: Entero no puede lanzar al IFN
- 26. Lanzar una excepción desde el evento AppDomain.AssemblyLoad
- 27. ¿Cómo puedo lanzar una excepción para toda la clase en lugar de hacerlo método mediante el método
- 28. La ejecución de un subproceso falla
- 29. ¿Está marcada la clase de excepción java?
- 30. Lanzar excepción pero persistir el seguimiento de la pila
¿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