todas tipos propagacion personalizadas mas manejo las excepciones errores ejemplos comunes arbol java concurrency executorservice futuretask

propagacion - tipos de excepciones en java netbeans



Cómo atrapar excepciones en FutureTask (5)

Después de encontrar que FutureTask ejecuta en un Executors.newCachedThreadPool() en Java 1.6 (y de Eclipse) se traga las excepciones en el método Runnable.run() , he intentado encontrar una manera de atraparlas sin agregar tiradas / atrapadas a Todas mis implementaciones de Runnable .

La API sugiere que anular FutureTask.setException() debería ayudar en esto:

Hace que este futuro reporte una ExecutionException con la tirable dada como su causa, a menos que este Futuro ya haya sido establecido o haya sido cancelado. Este método es invocado internamente por el método de ejecución en caso de falla del cálculo.

Sin embargo, no parece que se haya llamado a este método (al ejecutar con el depurador, FutureTask la excepción, pero no se llama a setException ). He escrito el siguiente programa para reproducir mi problema:

public class RunTest { public static void main(String[] args) { MyFutureTask t = new MyFutureTask(new Runnable() { @Override public void run() { throw new RuntimeException("Unchecked exception"); } }); ExecutorService service = Executors.newCachedThreadPool(); service.submit(t); } } public class MyFutureTask extends FutureTask<Object> { public MyFutureTask(Runnable r) { super(r, null); } @Override protected void setException(Throwable t) { super.setException(t); System.out.println("Exception: " + t); } }

Mi pregunta principal es: ¿Cómo puedo detectar las excepciones lanzadas en una tarea futura? ¿Por qué no se setException a setException ?

También me gustaría saber por qué Thread.UncaughtExceptionHandler no utiliza el mecanismo FutureTask , ¿existe algún motivo para ello?


¿Has intentado usar un UncaughtExceptionHandler ?

  • Necesita implementar la interfaz UncaughtExceptionHandler .
  • Para configurar UncaughtExceptionHandler para subprocesos de grupo, proporcione un ThreadFactory en la llamada Executor.newCachedThreadPool(ThreadFactory) .
  • Puede establecer UncaughtExceptionHandler para el subproceso creado a través de setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

Envíe las tareas con ExecutorService.execute , porque solo las excepciones generadas por las tareas enviadas con execute hacen al controlador de excepciones no capturadas. Para las tareas enviadas con ExecutorService.execute cualquier excepción lanzada se considera parte del valor de retorno de la tarea. Si una tarea enviada con el envío finaliza con una excepción, se vuelve a generar cuando se llama a Future.get , envuelto en una ExecutionException


Hay tres formas estándar y una forma improvisada. 1. use UncaughtExceptionHandler, configure el UncaughtExceptionHandler para el hilo creado como

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable ex) {..}}

* Pero la limitación es que atrapa la excepción lanzada por hilo pero en caso de una tarea futura, se traga. 2. use afterExecute después de crear un ejecutor de subprocesos personalizado con gancho que se haya proporcionado especialmente para este propósito. Mirando a través del código de ThreadpoolExecutor, a través de enviar> ejecutar (hay un workQueue, workQueue.offer ), las tareas se agregan a la cola de trabajo

final void runWorker(Worker arg0) { Thread arg1 = Thread.currentThread(); Runnable arg2 = arg0.firstTask; .. while(arg2 != null || (arg2 = this.**getTask()**) != null) { arg0.lock(); .. try { this.beforeExecute(arg1, arg2); Object arg4 = null; try { arg2.run(); } catch (RuntimeException arg27) { .. } finally { this.**afterExecute**(arg2, (Throwable)arg4); } } getTask() {.. this.workQueue.**poll**(); ..}

  1. Luego, el tercero está utilizando la captura de prueba simple dentro del método de llamada, pero no puede detectar la excepción fuera de aquí.

  2. La solución es llamar a todos los métodos de llamada desde un método de llamada de TaskFactory, una fábrica que libera callables.


He mirado el código fuente de FutureTask y no pude encontrar dónde se llama a setException .
Hay un método innerSetException de FutureTask.Sync (clase interna de FutureTask ) que se llama en caso de que un Throwable sea ​​lanzado por el método de ejecución. Este método también se llama en setException .
Así que parece que el javadoc no es correcto (o muy difícil de entender ...).


Una solución mucho mejor: Java FutureTask.

Cuando llama a futureTask.get() para recuperar el resultado del cálculo, generará una excepción (ExecutionException) si el Runnable / Callable subyacente lanzó una excepción.

ExecutionException.getCause() devolverá la excepción que el Runnable / Callable lanzó.

También lanzará una excepción diferente si el Runnable / Callable fue cancelado.


setException probable que setException no esté hecho para anular, pero se proporciona para permitirle establecer el resultado en una excepción, si fuera necesario. Lo que quieres hacer es anular el método done() y tratar de obtener el resultado:

public class MyFutureTask extends FutureTask<Object> { public MyFutureTask(Runnable r) { super(r, null); } @Override protected void done() { try { if (!isCancelled()) get(); } catch (ExecutionException e) { // Exception occurred, deal with it System.out.println("Exception: " + e.getCause()); } catch (InterruptedException e) { // Shouldn''t happen, we''re invoked when computation is finished throw new AssertionError(e); } } }