2014-12-03 11 views
12

Una discussione nel Code Review chat determinato il seguente comportamento da uno ScheduledExecutorService:ScheduledExecutorService e errore non rilevato

un'operazione pianificata per eseguire fallisce con un problema 'serio', ma non c'è nessun rapporto, eccezione o log del problema . In altri contesti, l'applicazione normalmente terminerebbe con un errore. Nel contesto di ScheduledExecutorService, tuttavia, non esiste alcuna "gestione" di eccezione/errore.

In primo luogo, per fabbricare un problema. La seguente classe ha un inizializzatore statico che è garantito per fallire:

public class InitializerFault { 

    private static final int value = Integer.parseInt("fubar"); 

    @Override 
    public String toString() { 
     return "" + value; 
    } 

} 

Quando condotta secondo:

public static void main(String[] args) { 
    System.out.println(new InitializerFault()); 
} 

produce (che è esattamente quello che mi sarei aspettato):

Exception in thread "main" java.lang.ExceptionInInitializerError 
    at SimpleHandler.main(SimpleHandler.java:5) 
Caused by: java.lang.NumberFormatException: For input string: "fubar" 
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 
    at java.lang.Integer.parseInt(Integer.java:580) 
    at java.lang.Integer.parseInt(Integer.java:615) 
    at InitializerFault.<clinit>(InitializerFault.java:4) 
    ... 1 more 

Ma, quando eseguito come:

private static final Thread buildThread(Runnable r) { 
    Thread t = new Thread(r, "TestThread"); 
    t.setDaemon(true); 
    System.out.println("Built thread " + t); 
    return t; 
} 
public static void main(String[] args) throws InterruptedException { 
    // use a thread factory to create daemon threads ... can be non-daemon as well. 
    ScheduledExecutorService ses = Executors.newScheduledThreadPool(
      2, (r) -> buildThread(r)); 
    ses.scheduleAtFixedRate(
      () -> {System.out.println(new InitializerFault());}, 
      500, 1000, TimeUnit.MILLISECONDS); 
    Thread.sleep(3000); 
    System.out.println("Exiting"); 
} 

Produce solo:

Built thread Thread[TestThread,5,main] 
Exiting 

Non v'è alcuna menzione di eventuali errori, non per colpa, no discarica, niente. Questo ExceptionInInitializerError ha provocato un complicato processo di debug nella vita reale, in cui il problema era molto difficile da isolare.

due domande:

  1. è questo un comportamento previsto Java, che gli errori nel Esecutori sono 'ignorati'?
  2. qual è il modo giusto per gestire questa situazione?
+0

Questo può aiutare [Gestione delle eccezioni in ThreadPools] (http://stackoverflow.com/questions/3875739/exception-handling-in-threadpools/3875968# 3875968) –

risposta

4

ScheduledExecutorService.scheduleAtFixedRate restituisce un ScheduledFuture. Se chiamiamo il numero ScheduledFuture.get(), il thread si bloccherà e attenderà il completamento periodico dell'attività, che potrebbe verificarsi in caso di annullamento dell'attività o se l'attività genera un'eccezione. In quest'ultimo caso get() lancerà java.util.concurrent.ExecutionException con l'eccezione originale spostata

+4

Giusto, ora ho provato questo, e (ovviamente) hai ragione, lo fa. Mentre la tua risposta è giusta, è una brutta soluzione ... Il vero compito stesso fa regolare gestione delle eccezioni con i blocchi try/catch, ma non intrappola l'errore ... Inoltre, "aspetta" sul thread principale (o un non Thread Executor) non è molto pratico. Se volessi bloccare lì, non avrei usato il ritardo. Non è colpa tua, ma la tua soluzione suggerita è 'brutta'. – rolfl