what - exception hierarchy in java
¿Cómo lanzar una excepción marcada de un hilo de Java? (9)
Hola, estoy escribiendo una aplicación de red, en la que leo paquetes de algún formato binario personalizado. Y estoy comenzando un hilo de fondo para esperar los datos entrantes. El problema es que el compilador no me permite poner excepciones de código arrojando (marcado) en run()
. Dice:
run() in (...).Listener cannot implement run() in java.lang.Runnable; overridden method does not throw java.io.IOException
Quiero que la excepción mate el hilo, y que quede atrapado en algún lugar del hilo padre. ¿Es posible lograr esto o tengo que manejar cada excepción dentro del hilo?
Advertencia: esto puede no satisfacer sus necesidades si tiene que usar el mecanismo de excepción.
Si lo entiendo correctamente, en realidad no necesita que se verifique la excepción (ha aceptado la respuesta que sugiere una excepción sin marcar), ¿sería más apropiado un patrón de oyente simple?
El oyente podría vivir en el hilo padre, y cuando haya capturado la excepción marcada en el hilo secundario, simplemente podría notificar al oyente.
Esto significa que tiene una forma de exponer que esto sucederá (a través de métodos públicos), y podrá pasar más información de la permitida por una excepción. Pero sí significa que habrá un acoplamiento (aunque suelto) entre el padre y el hilo hijo. Dependería de su situación específica si esto tendría un beneficio sobre envolver la excepción marcada con una desactivada.
Aquí hay un ejemplo simple (algún código tomado de otra respuesta):
public class ThingRunnable implements Runnable {
private SomeListenerType listener;
// assign listener somewhere
public void run() {
try {
while(iHaveMorePackets()) {
doStuffWithPacket();
}
} catch(Exception e) {
listener.notifyThatDarnedExceptionHappened(...);
}
}
}
El acoplamiento proviene de un objeto en el hilo principal que debe ser del tipo SomeListenerType
.
Envolver su excepción dentro de una RuntimeException
parece ser el truco.
someMethod() throws IOException
{
try
{
new Thread(() ->
{
try
{
throw new IOException("a checked exception thrown from within a running thread");
}
catch(IOException ex)
{
throw new RuntimeException("a wrapper exception", ex); // wrap the checked exception inside an unchecked exception and throw it
}
}).start();
}
catch(RuntimeException ex) // catch the wrapped exception sent from within the thread
{
if(ex.getCause() instanceof IOException)
throw ex.getCause; // unwrap the checked exception using getCause method and use it however you need
else
throw ex;
}
}
Esta respuesta se basa en Esko Luontola uno, pero proporciona un ejemplo de trabajo.
A diferencia del método run () de la interfaz Runnable, el método call () de Callable permite lanzar algunas excepciones. Aquí hay un ejemplo de implementación:
public class MyTask implements Callable<Integer> {
private int numerator;
private int denominator;
public MyTask(int n, int d) {
this.numerator = n;
this.denominator = d;
}
@Override
// The call method may throw an exception
public Integer call() throws Exception {
Thread.sleep(1000);
if (denominator == 0) {
throw new Exception("cannot devide by zero");
} else {
return numerator / denominator;
}
}
}
El ejecutor proporciona un mecanismo para ejecutar un invocable dentro de un hilo y para manejar cualquier tipo de excepciones:
public class Main {
public static void main(String[] args) {
// Build a task and an executor
MyTask task = new MyTask(2, 0);
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
try {
// Start task on another thread
Future<Integer> futureResult = threadExecutor.submit(task);
// While task is running you can do asynchronous operations
System.out.println("Something that doesn''t need the tasks result");
// Now wait until the result is available
int result = futureResult.get();
System.out.println("The result is " + result);
} catch (ExecutionException e) {
// Handle the exception thrown by the child thread
if (e.getMessage().contains("cannot devide by zero"))
System.out.println("error in child thread caused by zero division");
} catch (InterruptedException e) {
// This exception is thrown if the child thread is interrupted.
e.printStackTrace();
}
}
}
Lo que hago es capturar la excepción en el hilo y almacenarla como una variable miembro de Runnable. Esta excepción se expone luego a través de un getter en Runnable. Luego escaneo todos los hilos del padre para ver si hubo excepciones y tomo las medidas adecuadas.
Para poder enviar la excepción al hilo padre, puede poner su hilo de fondo en un Callable (permite lanzar también las excepciones marcadas) que luego pasa al método de submit de algún ejecutor . El método de envío devolverá un Future que luego podrá usar para obtener la excepción (su método get arrojará una ExecutionException que contiene la excepción original).
Si el código de su hilo arroja una RuntimeExpection, no necesita agregar la excepción run () throw.
Pero use esta solución solo cuando sea apropiado porque puede ser una mala práctica: http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html
Cualquier excepción de RuntimeException o no seleccionada puede ayudarte. Tal vez necesites crear tu propia RuntimeException
Si realmente no puede hacer nada útil cuando se produce la excepción, puede envolver la excepción marcada en una RuntimeException.
try {
// stuff
} catch (CheckedException yourCheckedException) {
throw new RuntimeException("Something to explain what is happening", yourCheckedException);
}
Suponiendo que su código está en algún tipo de bucle, usted escribiría:
public class ThingRunnable implements Runnable {
public void run() {
try {
while(iHaveMorePackets()) {
doStuffWithPacket()
}
} catch(Exception e) {
System.out.println("Runnable terminating with exception" + e );
}
}
}
La excepción saldrá automáticamente de su ciclo, y al final del método run (), el hilo se detendrá.
el hilo no puede lanzar la excepción a ningún otro hilo (ni al hilo principal). y no puede hacer que el método heredado run () arroje ninguna excepción comprobada ya que solo puede arrojar menos del código heredado, no más.