2015-11-17 13 views
14

Implemento MyInputStream.read() e noto che un InterruptedException può accadere all'interno di questa funzione. Dopo qualche ricerca ho scoperto che è comune a prendere il InterruptedException e ri-lanciare un InterruptedIOException, qualcosa di simile:Devo fare `Thread.currentThread(). Interrupt()` prima di lanciare un nuovo InterruptedIOException() `?

try { 
     ... 
    } catch (InterruptedException e) { 
     //Thread.currentThread().interrupt(); // <=== ??? 
     throw new InterruptedIOException(); 
    } 

ma solo circa il 50% dei campioni di codice fare Thread.currentThread().interrupt(). Bene, si è convenuto che the worst thing you can do with InterruptedException is swallow it, ma si dovrebbe reinterrupt il thread corrente prima di generare un'eccezione diversa?

PRO: una singola richiesta di interruzione può avere più "destinatari".

CONTRA: alcune funzionalità like logging potrebbero non funzionare prima che lo stato di interruzione venga cancellato, il che potrebbe causare bug sottili.

CONTRA: otteniamo due notifiche sulla richiesta di interrupt: lo stato interrotto del thread e l'eccezione. Inizialmente, c'è una sola notifica: o lo stato interrotto del thread è vero o viene lanciato uno, ma non entrambi.

PRO: nessuno verifica realmente il codice contro le eccezioni di I/O che possono essere generate e lo InterruptedIOException è diverso da altre eccezioni di I/O; una clausola catch(IOException) potrebbe ingoiare lo stato interrotto.

PS Sembra che qualunque cosa io faccia, il problema è che InterruptedIOException è un tipo molto speciale di IOException che richiede che un gestore speciale non venga risolto.

PPS (EDIT) Non posso lasciare l'originale InterruptedException propagano perché InputStream.read() non può buttare InterruptedExceptionthrows IOException e non si butta niente altro). E non posso prevedere il contesto in cui verrà chiamato MyInputStream.read(): un'istanza di MyInputStream può essere passata a qualsiasi funzione di libreria Java o di terze parti che accetta un argomento InputStream.

Per quanto riguarda the old bug, sembra che sia stato appena chiuso, non risolto; e l'idea stessa dello stato interrotto è che il codice si comporterebbe diversamente.

+0

Quello che non mi piace da 'InterruptedIOException' è che non facilita l'incorporamento di altre eccezioni come causa.A seconda del contesto, dovrei semplicemente "lanciare una nuova IOException (e)" in modo che possa ancora ottenere la causa sottostante quando ho rilevato l'eccezione nel livello superiore. –

risposta

1

Suggerisco di lanciare un ClosedByInterruptException. Sebbene appartenga alla libreria NIO, ha un'API meglio definita rispetto al vecchio InterruptedIOException, che semplifica la gestione. Ad esempio:

try { 
    ... 
} catch (InterruptedException e) { 
    close(); // obeying API of ClosedByInterruptException 
    Thread.currentThread().interrupt(); // again, obeying API 
    throw new ClosedByInterruptException(); 
} 

Vedere anche Thread#interrupt(). Se invece vuoi rilanciare l'eccezione originale, puoi utilizzare:

try { 
    ... 
} catch (InterruptedException e) { 
    throw e; 
} 

Quindi mantieni la traccia dello stack. In questo caso lo stato dell'interrupt è lasciato vuoto, come suggerisce l'API per InterruptedException.

+0

Questa risposta sembra la migliore. Come [Stephen] (http://stackoverflow.com/a/33757384/2402790) dice, il contrario del poster sullo stato di interruzione e la registrazione può essere tranquillamente scontato. E il contrario di due notifiche è qui indicato dal significato chiaro e preciso di ClosedByInterruptException. –

1

... devo reinterruptare il thread corrente prima di generare un'eccezione diversa?

Se qualcosa di upstack sta per esaminare la flag di interrupt, quindi sì. Altrimenti, non importa.

CONTRA: alcune funzionalità come la registrazione potrebbero non funzionare prima che lo stato di interruzione venga cancellato, il che potrebbe causare bug sottili.

Dalla lettura dell'analisi, il bug che si è collegato si applica solo a Java 6 e versioni precedenti e solo per la piattaforma Solaris. Probabilmente puoi scontarlo ora. (A meno che non si dispone di un cliente con tasche Deeeep, non si dovrebbe essere facendo applicazione significativa per Java 6 o versioni precedenti.)

CONTRA: otteniamo due notifiche relative alla richiesta di interruzione: lo stato interrotto il filo e l'eccezione.

sono qualitativamente diversi tipi di notifica ...

PS Sembra che tutto quello che faccio, il problema che InterruptedIOException è un tipo molto particolare di IOException richiede un gestore speciale non sarà risolto.

In realtà, una strategia migliore potrebbe essere quella di impostare il flag interrotto nella cattura per la InterruptedIOException ... o semplicemente consentire l'eccezione originale Interrupted per propagarsi.

1

A causa del seguente ragionamento:

  1. InterruptedException NON DEVE essere ingerito,

  2. qualsiasi IOException (e, in particolare, InterruptedIOException) possono inghiottire, cioè, consumato dalla 3a parte codice

  3. IOException ha lo scopo di informare sugli eventi che si verificano con i/o, non sui cambiamenti nello stato del thread

  4. un codice che non possiamo controllare la facoltà di fissare o deselezionare il filo interrotto di stato prima di lanciare o ri-lanciare InterruptedIOException

ho deciso che:

  1. la corrente deve filo essere reinterrupted prima di lanciare un InterruptedIOException.
  2. la movimentazione InterruptedIOException NON DEVONO assumere alcuna particolare stato del filo interrotto stato
  3. questo comportamento deve essere documentato codice:

    @throws InterruptedIOException if the current thread is interrupted (the thread 
         interrupted status is true when InterruptedIOException is thrown) 
    @throws IOException if this stream is closed or another IOException occurs. 
    
    Note that due to possible interference from 3rd-party code, handlers 
    of InterruptedIOException should not assume any particular state 
    of the thread interrupted status when they are invoked. 
    
Problemi correlati