2016-06-10 29 views
7

Se si utilizza il seguente "idioma" con interruzione in Java, ad esempio from this answer.È possibile un controllo di interruzione "atomico" in java?

while (!Thread.currentThread().isInterrupted()) { 
    try { 
     Object value = queue.take(); 
     handle(value); 
    } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
    } 
} 

Dove take è un'operazione di blocco, può un interrupt non essere ignorato per il momento, se un interrupt "arriva" tra il controllo della Thread.currentThread().isInterrupted() e la chiamata queue.take()? Non si tratta di un'operazione "check-than-act"? In tal caso, può essere in qualche modo garantito che il ciclo sia lasciato in ogni caso se il thread è interrotto?

È possibile utilizzare poll with a timeout in modo che il ciclo venga lasciato dopo il timeout, ma è possibile controllare lo stato interrotto e agire su di esso atomicamente?

+2

Come potrebbe mai essere interrotto un interrupt dal codice sopra riportato? Ti rendi conto che queue.take() verrà lanciato immediatamente se il thread viene interrotto prima che la chiamata prenda(), giusto? –

+0

@JBNizet: Ho controllato il codice, e hai ragione, i metodi che lanciano il controllo 'InterruptedException' per lo stato interrotto e il lancio. Se aggiungi una risposta, la accetterò. – user140547

risposta

3

Vorrei scambiare il try/catch e ciclo while:

try { 
    while (true) { 
    Object value = queue.take(); 
    handle(value); 
    } 
} catch (InterruptedException e) { 
    Thread.currentThread().interrupt(); 
} 

L'operazione take() getterà un InterruptedException immediatamente se il filo si interrompe, e allo stesso intervallo di tempo fuori dal ciclo while.

+0

Durante l'interruzione durante la gestione, l'eccezione non può essere generata. Quindi, per sicurezza, di solito uso mentre (! Thread.currentThread(). IsInterrupted()) – gusto2

+0

@GabrielVince Si prega di spiegare le circostanze in "l'eccezione non può essere generata". –

+0

nel caso in cui il metodo "handle (..)" stia facendo alcuni calcoli, non necessariamente in attesa di I/O e il thread è interrotto, L'eccezione non viene generata. Lo controllerei nel ciclo. Non penserei che il blocco I/O genererà un'eccezione quando il thread sta entrando con stato già interrotto (anche se il commento di JB.Nizet indica diversamente e potrei sbagliarmi qui). – gusto2

0

Solo una chiamata può cancellare la bandiera interrotta in modo che nulla possa accadere tra isInterrupted e queue.take().

0

ma è possibile controllare lo stato interrotto e agire su di esso atomicamente

Bene - Non so cosa vuoi dire "atomicamente" qui. Possiamo presumere che tu voglia qualcosa come onInterrupt (...)?

Gli interrupt hanno lo scopo di "interrompere" il thread, quindi tutte le operazioni di I/O predefinite generano un InterruptedException che è possibile rilevare o controllare. Dà ai thread l'opportunità di smettere di chiudere/liberare con garbo qualsiasi risorsa bloccata.

Per la gestione degli eventi è possibile implementare uno Cancellable task, in cui è possibile gestire i propri eventi di annullamento (beh, non gli interrupt JRE predefiniti).