Best practice per la gestione delle eccezioni nei thread Java

4

Lettore di lunga data, richiedente per la prima volta qui. Ho un servizio che scrive dati in un database in lotti. Contiene un buffer che viene guardato da un thread separato. Ogni volta che il buffer raggiunge una determinata dimensione o un certo periodo di tempo è trascorso dall'ultima scrittura, il thread scrive i dati nel DB.

In Java, ogni volta che c'è un'eccezione nel thread del monitor, muore silenziosamente e non fa mai più nulla.

Esiste una best practice consolidata sulla gestione delle eccezioni in tali thread? Il thread deve essere in esecuzione in ogni momento e dovrebbe stampare un'eccezione nel log se si verifica uno.

Ci sono alcune potenziali soluzioni a questo che mi vengono in mente:

  1. Avvolgi gli interi metodi nei blocchi try / catch, cattura tutte le eccezioni e chiedi a un Logger di stampare i messaggi. (Troppo brutto per i miei gusti)
  2. Registrare un gestore di eccezioni non rilevate e gestire le eccezioni presenti. (Forse?)
  3. Non usare una Discussione, ma un Callable o un Runnable. (Non sono sicuro che sia adatto a thread sempre attivi)
  4. Qualcos'altro?
posta JohnEye 28.03.2018 - 14:05
fonte

2 risposte

3

In primo luogo, non ho capito a cosa serve il thread del monitor e qual è il suo scopo. L'unica ragione per cui posso pensare è se il thread del monitor è un thread in esecuzione continua che guarda solo il buffer e chiama periodicamente la scrittura del database. Se questo è lo scopo, preferirei farlo con gli scheduler, ad es. pianificare una scrittura ogni n secondi e scrivere l'intero buffer nel database. Quindi devi solo approssimare quanti secondi hai bisogno che la frequenza dello scheduler sia in ordine perché il buffer non possa traboccare.

Per quanto riguarda la gestione delle eccezioni nei thread, vorrei prima riprovare la scrittura. Alla fine, se tutto fallisce, la prima cosa che dovresti fare è recuperare i dati in modo da non perderli.

Il modo in cui le eccezioni devono essere gestite è identificare le eccezioni che possono verificarsi e quindi gestire solo quelle eccezioni specifiche. Non dovresti mai fare cose come catch (Exception e) . Dal momento che il servizio di scrittura DB è un servizio generale, vorrei che propagasse l'eccezione al chiamante e che il chiamante gestisse l'eccezione, poiché il servizio non può sapere quale comportamento vuole il chiamante.

Per quanto riguarda il modo in cui dovresti gestire le eccezioni specifiche, tocca a te e difficilmente qualcuno può aiutarti in questo. Se non riesci a gestire le eccezioni nel blocco finally e hanno bisogno dell'attenzione dello sviluppatore, vorrei registrarli o informare lo sviluppatore tramite un canale di comunicazione alternativo, ad es. email, Slack.

    
risposta data 28.03.2018 - 15:40
fonte
2

Non hai mai menzionato se le eccezioni generate DEVONO essere gestite / registrate dal thread principale o meno. Presumo "non importa, ho solo bisogno di registrare l'eccezione ed evitare il danneggiamento del thread".

Se la mia ipotesi è corretta, potrebbe semplicemente essere necessario mettere il try / catch sul metodo run di Runnable, ma tale metodo deve essere eseguito su un ciclo infinito e deve essere interrotto una volta ogni tanto:

final Thread t = new Thread(new Runnable(){
    @Override
    public void run(){
          long lastTimeFlushed = getCurrentTime();
          while(true){
                try{
                     if(bufferLimitExceeded() || timeoutExceeded(lastTimeFlushed)){
                           flushToDB();
                           lastTimeFlushed = getCurrentTime();
                     } 
                     Thread.sleep(500);
                }catch(final InterruptedException ex){
                     // you'll need to decide whether to ignore or not thread's interruption
                     // This example is in case you decide not to ignore it
                     Thread.currentThread().interrupt();
                }catch(final Exception ex){
                     logError(ex);
                } 
          } 
     } 
});

t.start();

In questo modo, il tuo thread non morirà e dovrai solo aggiungere try / catch in un unico punto .

Dichiarazione di non responsabilità: l'ho scritto usando il mio telefono. Scusa se ci sono errori di battitura (specialmente nel codice)

    
risposta data 30.03.2018 - 06:20
fonte