2014-12-03 10 views
12

dyskusja w Code Review chat określane następujące zachowanie z punktu A ScheduledExecutorService:ScheduledExecutorService i nieprzechwycony Błąd

Zadanie zaplanowane powiedzie się z „poważnego” problem, ale nie ma raportu, wyjątek lub dziennika problemu . W innych kontekstach aplikacja normalnie kończyłaby się błędem. Jednak w kontekście ScheduledExecutorService w ogóle nie ma "obsługi wyjątków/błędów".

Po pierwsze, aby wyprodukować problem. Poniższa klasa ma statyczny inicjator, który jest gwarantowany na niepowodzenie:

public class InitializerFault { 

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

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

} 

Przy wykorzystaniu:

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

produkuje (co jest dokładnie to, czego można się spodziewać):

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 

Ale w przypadku:

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"); 
} 

produkuje tylko:

Built thread Thread[TestThread,5,main] 
Exiting 

Nie ma wzmianki o błędach, żadnych błędach, żadnych zrzutach, niczym. Ten wyjątek ExceptionInInitializerError spowodował skomplikowany proces debugowania w czasie rzeczywistym, w którym problem był bardzo trudny do wyizolowania.

dwa pytania:

  1. jest to oczekiwane zachowanie Java, że ​​błędy w Wykonawcami są 'ignorowane'?
  2. jaki jest właściwy sposób na rozwiązanie tej sytuacji?
+0

To może ci pomóc [Obsługa wyjątków w ThreadPools] (http://stackoverflow.com/questions/3875739/exception-handling-in-threadpools/3875968# 3875968) –

Odpowiedz

4

ScheduledExecutorService.scheduleAtFixedRate zwraca ScheduledFuture. Jeśli zadzwonimy pod numer ScheduledFuture.get(), wątek zostanie zablokowany i będzie czekał na okresowe zakończenie zadania, które może się zdarzyć w przypadku anulowania zadania lub jeśli zadanie zgłasza wyjątek. W tym drugim przypadku get() rzuci java.util.concurrent.ExecutionException z owiniętym oryginalnym wyjątkiem

+4

Dobrze, teraz próbowałem tego i (oczywiście) masz rację, to robi. Podczas gdy twoja odpowiedź jest właściwa, jest to brzydkie rozwiązanie ... Prawdziwe zadanie samo zajmuje się wyjątkową obsługą wyjątków z blokami try/catch, ale nie przechwytuje błędu ... Dodatkowo, "czekanie" na główny wątek (lub Wątek executora) nie jest zbyt praktyczny. Gdybym chciał tam zablokować, nie skorzystalbym z opóźnienia. To nie twoja wina, ale twoje sugerowane rozwiązanie jest "brzydkie". – rolfl

Powiązane problemy