Che cosa fa java.lang.Thread.interrupt ()?


Risposte:


251

Thread.interrupt()imposta lo stato / flag interrotto del thread di destinazione. Quindi il codice in esecuzione nel thread di destinazione PUO 'eseguire il polling dello stato interrotto e gestirlo in modo appropriato. Alcuni metodi che bloccano come Object.wait()possono consumare immediatamente lo stato interrotto e generare un'eccezione appropriata (di solito InterruptedException)

L'interruzione in Java non è preventiva. In altri termini, entrambi i thread devono cooperare per elaborare correttamente l'interrupt. Se il thread di destinazione non esegue il polling dello stato interrotto, l'interrupt viene effettivamente ignorato.

Il polling si verifica tramite il Thread.interrupted()metodo che restituisce lo stato interrotto del thread corrente E cancella il flag di interruzione. Di solito il thread potrebbe quindi fare qualcosa come buttare InterruptedException.

EDIT (dai commenti di Thilo): alcuni metodi API hanno incorporato la gestione degli interrupt. Della parte superiore della mia testa questo include.

  • Object.wait(), Thread.sleep()eThread.join()
  • La maggior parte delle java.util.concurrentstrutture
  • Java NIO (ma non java.io) e NON utilizza InterruptedException, invece di utilizzare ClosedByInterruptException.

EDIT (dalla risposta di @ thomas-pornin alla stessa domanda per completezza)

L'interruzione del thread è un modo delicato per spingere un thread. È usato per dare ai thread la possibilità di uscire in modo pulito , al contrario di Thread.stop()quello è più come sparare al filo con un fucile d'assalto.


22
Si noti che metodi come sleep o wait eseguono questo tipo di polling e generano InterruptedException da soli.
Thilo,

1
Se si utilizza l'I / O di file interrompibile, l'effetto non sarà così delicato. In genere si ottiene la corruzione dei file.
Marko Topolnik,

se stai citando Thread.interrupted, sembra che dovrebbe essere menzionato che esiste anche un flag Thread.isInterrupted, che non cancella il flag, il che lo rende di solito più appropriato per l'uso da parte degli sviluppatori di applicazioni.
Nathan Hughes,

67

Che cos'è l'interrupt?

Un interrupt indica a un thread che dovrebbe interrompere ciò che sta facendo e fare qualcos'altro. Spetta al programmatore decidere esattamente come un thread risponde a un interrupt, ma è molto comune che il thread termini.

Come viene implementato?

Il meccanismo di interruzione viene implementato utilizzando un flag interno noto come stato di interruzione. Richiamare Thread.interrupt imposta questo flag. Quando un thread verifica la presenza di un interrupt invocando il metodo statico Thread.interrupt, lo stato di interruzione viene cancellato. Thread.isInterrupted non statico, utilizzato da un thread per interrogare lo stato di interruzione di un altro, non modifica il flag di stato di interruzione.

Citazione Thread.interrupt()dall'API :

Interrompe questo thread. Innanzitutto viene invocato il metodo checkAccess di questo thread, che può causare il lancio di SecurityException.

Se questo thread è bloccato in una chiamata dei metodi wait (), wait (long) o wait (long, int) della classe Object o di join (), join (long), join (long, int) , sleep (long) o sleep (long, int), metodi di questa classe, quindi il suo stato di interruzione verrà cancellato e riceverà una InterruptedException.

Se questo thread viene bloccato in un'operazione I / O su un canale interrompibile, il canale verrà chiuso, verrà impostato lo stato di interruzione del thread e il thread riceverà un ClosedByInterruptException.

Se questo thread è bloccato in un Selettore, lo stato di interruzione del thread verrà impostato e tornerà immediatamente dall'operazione di selezione, possibilmente con un valore diverso da zero, proprio come se fosse stato invocato il metodo di attivazione del selettore.

Se nessuna delle condizioni precedenti è valida, verrà impostato lo stato di interruzione di questo thread.

Dai un'occhiata a questo per una completa comprensione dello stesso:

http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html


Questa è obbedire a una spiegazione parziale. Inoltre interrompe i metodi interrompibili.
Marchese di Lorne,

@EJP Questa domanda riguarda: cos'è il metodo Thread.interrupt () e come funziona. Penso che qualunque cosa abbia pubblicato con link, risponda a ciò che viene chiesto. Non capisco ancora cosa desideri?
YoK,

Ti auguro di correggere la tua dichiarazione parzialmente errata che è implementata da una bandiera. Questa è solo una parte della storia. Mi sembra abbastanza chiaro.
Marchese di Lorne,

@EJP Grazie. Ora capisco cosa stavi dicendo. Ho aggiornato la mia risposta e aggiunto il documento API per il metodo. Questo riguarda la parte dei metodi interrompibili che mancava dalla mia risposta. Spero che la mia risposta sembri completa ora :).
YoK,

13

Se il thread di destinazione è stato in attesa (chiamando wait(), o altri metodi correlati che essenzialmente fanno la stessa cosa, come sleep()), verrà interrotto, il che significa che smette di aspettare ciò che stava aspettando e riceve invece un'interruzione di eccezione.

Sta completamente al thread stesso (il codice che ha chiamato wait()) decidere cosa fare in questa situazione. Non termina automaticamente il thread.

A volte viene utilizzato in combinazione con un contrassegno di terminazione. Se interrotto, il thread potrebbe controllare questo flag e quindi chiudersi. Ma ancora una volta, questa è solo una convenzione.


9 anni, risposta senza età! +1
snr

10

Per completezza, oltre alle altre risposte, se il thread viene interrotto prima che si blocchi Object.wait(..)o Thread.sleep(..)ecc., Ciò equivale a essere interrotto immediatamente dopo il blocco su quel metodo , come mostra l'esempio seguente.

public class InterruptTest {
    public static void main(String[] args) {

        Thread.currentThread().interrupt();

        printInterrupted(1);

        Object o = new Object();
        try {
            synchronized (o) {
                printInterrupted(2);
                System.out.printf("A Time %d\n", System.currentTimeMillis());
                o.wait(100);
                System.out.printf("B Time %d\n", System.currentTimeMillis());
            }
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("C Time %d\n", System.currentTimeMillis());

        printInterrupted(3);

        Thread.currentThread().interrupt();

        printInterrupted(4);

        try {
            System.out.printf("D Time %d\n", System.currentTimeMillis());
            Thread.sleep(100);
            System.out.printf("E Time %d\n", System.currentTimeMillis());
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("F Time %d\n", System.currentTimeMillis());

        printInterrupted(5);

        try {
            System.out.printf("G Time %d\n", System.currentTimeMillis());
            Thread.sleep(100);
            System.out.printf("H Time %d\n", System.currentTimeMillis());
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("I Time %d\n", System.currentTimeMillis());

    }
    static void printInterrupted(int n) {
        System.out.printf("(%d) Am I interrupted? %s\n", n,
                Thread.currentThread().isInterrupted() ? "Yes" : "No");
    }
}

Produzione:

$ javac InterruptTest.java 

$ java -classpath "." InterruptTest
(1) Am I interrupted? Yes
(2) Am I interrupted? Yes
A Time 1399207408543
WAS interrupted
C Time 1399207408543
(3) Am I interrupted? No
(4) Am I interrupted? Yes
D Time 1399207408544
WAS interrupted
F Time 1399207408544
(5) Am I interrupted? No
G Time 1399207408545
H Time 1399207408668
I Time 1399207408669

Implicazione: se esegui un ciclo come il seguente e l'interrupt si verifica nel momento esatto in cui il controllo è partito Thread.sleep(..)e gira intorno al loop, si verificherà comunque l'eccezione. Quindi è assolutamente sicuro fare affidamento sul fatto che InterruptedException viene lanciato in modo affidabile dopo l'interruzione del thread :

while (true) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ie) {
        break;
    }
}


4

L'interruzione del thread si basa sullo stato di interruzione del flag . Per ogni thread il valore predefinito dello stato di interrupt è impostato su false . Ogni volta che viene chiamato il metodo interrupt () sul thread, lo stato di interrupt è impostato su true .

  1. Se interrupt status = true (interrupt () già chiamato sul thread), quel particolare thread non può andare in modalità sleep. Se viene chiamato sleep su quel thread viene generata un'eccezione interrotta. Dopo aver lanciato nuovamente l'eccezione, il flag è impostato su false.
  2. Se il thread è già inattivo e viene chiamato interrupt () , il thread uscirà dallo stato di sospensione e genererà l'eccezione interrotta.

1

public void interrupt ()

Interrompe questo thread.

A meno che il thread corrente non si interrompa da solo, il che è sempre consentito, viene invocato il metodo checkAccess di questo thread, che può causare il lancio di SecurityException.

Se questo thread è bloccato in una chiamata dei metodi wait (), wait (long) o wait (long, int) della classe Object o di join (), join (long), join (long, int) , sleep (long) o sleep (long, int), metodi di questa classe, quindi il suo stato di interruzione verrà cancellato e riceverà una InterruptedException.

Se questo thread viene bloccato in un'operazione I / O su un canale interrompibile, il canale verrà chiuso, verrà impostato lo stato di interruzione del thread e il thread riceverà un ClosedByInterruptException.

Se questo thread è bloccato in un Selettore, lo stato di interruzione del thread verrà impostato e tornerà immediatamente dall'operazione di selezione, possibilmente con un valore diverso da zero, proprio come se fosse stato invocato il metodo di attivazione del selettore.

Se nessuna delle condizioni precedenti è valida, verrà impostato lo stato di interruzione di questo thread.

L'interruzione di un thread che non è vivo non deve avere alcun effetto.

Produce: SecurityException - se il thread corrente non può modificare questo thread



1

Il metodo Thread.interrupt () imposta il flag interno "stato di interruzione". Di solito quel flag è controllato dal metodo Thread.interrupted ().

Per convenzione, qualsiasi metodo esistente tramite InterruptedException deve cancellare il flag di stato degli interrupt.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.