O que faz java.lang.Thread.interrupt ()?

Respostas:

250

Thread.interrupt()define o status / sinalizador interrompido do encadeamento de destino. Em seguida, o código em execução nesse segmento de destino PODE pesquisar o status interrompido e tratá-lo adequadamente. Alguns métodos que bloqueiam como Object.wait()podem consumir o status interrompido imediatamente e geram uma exceção apropriada (geralmente InterruptedException)

A interrupção no Java não é preventiva. Em outras palavras, os dois threads precisam cooperar para processar a interrupção corretamente. Se o encadeamento de destino não pesquisar o status interrompido, a interrupção será efetivamente ignorada.

A pesquisa ocorre por meio do Thread.interrupted()método que retorna o status interrompido do encadeamento atual E limpa esse sinalizador de interrupção. Geralmente, o thread pode fazer algo como lançar InterruptedException.

EDIT (dos comentários do Thilo): alguns métodos de API foram criados no tratamento de interrupções. Do topo da minha cabeça, isso inclui.

  • Object.wait(),, Thread.sleep()eThread.join()
  • Maioria das java.util.concurrentestruturas
  • Java NIO (mas não java.io) e NÃO usa InterruptedException, em vez disso, usa ClosedByInterruptException.

EDIT (da resposta de @ thomas-pornin para exatamente a mesma pergunta por questões de integridade)

A interrupção do encadeamento é uma maneira suave de empurrar um encadeamento. É usado para dar aos fios a chance de sair de forma limpa , ao contrário do Thread.stop()que é mais como atirar no fio com um rifle de assalto.

Mike Q
fonte
22
Observe que métodos como dormir ou esperar fazem esse tipo de pesquisa e lançam a InterruptedException por si mesmos.
Thilo
1
Se você estiver usando E / S de arquivo interrompível, o efeito não será tão suave. Você normalmente terá corrupção de arquivos.
Marko Topolnik 6/11/16
se você estiver mencionando Thread.interrupted, parece que também deve haver um sinalizador Thread.isInterrupted, que não apaga o sinalizador, o que geralmente o torna mais apropriado para uso pelos desenvolvedores de aplicativos.
Nathan Hughes
67

O que é interrupção?

Uma interrupção é uma indicação para um encadeamento de que ele deve parar o que está fazendo e fazer outra coisa. Cabe ao programador decidir exatamente como um thread responde a uma interrupção, mas é muito comum que o thread termine.

Como é implementado?

O mecanismo de interrupção é implementado usando um sinalizador interno conhecido como status de interrupção. Invocar Thread.interrupt define esse sinalizador. Quando um encadeamento verifica uma interrupção invocando o método estático Thread.interrupted, o status da interrupção é limpo. O Thread.isInterrupted não estático, usado por um thread para consultar o status de interrupção de outro, não altera o sinalizador de status de interrupção.

Citação da Thread.interrupt()API :

Interrompe esse segmento. Primeiro, o método checkAccess desse encadeamento é invocado, o que pode causar o lançamento de uma SecurityException.

Se esse encadeamento estiver bloqueado em uma invocação dos métodos wait (), wait (long) ou wait (long, int) da classe Object, ou dos métodos join (), join (), join (long), join (long, int) , sleep (long) ou sleep (long, int), dessa classe, seu status de interrupção será limpo e ele receberá uma InterruptedException.

Se esse encadeamento estiver bloqueado em uma operação de E / S em um canal interruptível, o canal será fechado, o status de interrupção do encadeamento será definido e o encadeamento receberá uma ClosedByInterruptException.

Se esse encadeamento estiver bloqueado em um seletor, o status de interrupção do encadeamento será definido e retornará imediatamente da operação de seleção, possivelmente com um valor diferente de zero, como se o método de ativação do seletor fosse invocado.

Se nenhuma das condições anteriores for mantida, o status de interrupção deste encadeamento será definido.

Verifique isso para um entendimento completo sobre o mesmo:

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

YoK
fonte
Isto é obedecer uma explicação parcial. Ele também interrompe métodos interrompíveis.
Marquês de Lorne
@EJP Esta questão é sobre o que é o método Thread.interrupt () e como ele funciona. Eu acho que tudo o que eu publiquei com o link responde ao que é solicitado. Eu ainda não entendo o que você deseja?
YoK 28/08/10
Desejo que você corrija sua declaração parcialmente incorreta de que ela é implementada por um sinalizador. Isso é apenas parte da história. Parece-me bastante claro.
Marquês de Lorne
@EJP Obrigado. Agora eu entendo o que você estava dizendo. Atualizei minha resposta e adicionei o documento da API para o método Isso abrange a parte dos métodos interruptíveis que estava faltando na minha resposta. Espero que minha resposta esteja completa agora :).
Yok
13

Se o segmento de destino estiver aguardando (chamando wait()ou alguns outros métodos relacionados que essencialmente fazem a mesma coisa, como sleep()), ele será interrompido, o que significa que ele pára de esperar o que estava esperando e recebe uma InterruptedException.

Depende completamente do próprio encadeamento (o código chamado wait()) decidir o que fazer nessa situação. Não encerra automaticamente o encadeamento.

Às vezes, é usado em combinação com um sinalizador de terminação. Quando interrompido, o thread pode verificar esse sinalizador e, em seguida, desligar-se. Mas, novamente, isso é apenas uma convenção.

Thilo
fonte
9 anos de idade, resposta sem idade! +1
snr
10

Para completar, além das outras respostas, se o encadeamento for interrompido antes de ser bloqueado Object.wait(..)ou assim por diante Thread.sleep(..), isso equivale a ser interrompido imediatamente após o bloqueio nesse método , como mostra o exemplo a seguir.

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

Resultado:

$ 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

Implicação: se você fizer um loop como o seguinte, e a interrupção ocorrer no momento exato em que o controle saiu Thread.sleep(..)e está dando a volta no loop, a exceção ainda ocorrerá. Portanto, é perfeitamente seguro confiar no lançamento da InterruptedException após a interrupção do encadeamento :

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

A interrupção do encadeamento é baseada no status de interrupção do sinalizador . Para cada segmento, o valor padrão do status de interrupção é definido como false . Sempre que o método interrupt () é chamado no thread, o status da interrupção é definido como true .

  1. Se status de interrupção = verdadeiro (interrupt () já chamado no encadeamento), esse encadeamento específico não poderá entrar em suspensão. Se o sono for chamado nesse segmento, a exceção interrompida será lançada. Depois de lançar a exceção novamente, o sinalizador é definido como falso.
  2. Se o thread já estiver inativo e interrupt () for chamado, o thread sairá do estado de inatividade e lançará uma exceção interrompida.
akash G
fonte
1

interrupção de vazio público ()

Interrompe esse segmento.

A menos que o encadeamento atual esteja se interrompendo, o que é sempre permitido, o método checkAccess desse encadeamento é invocado, o que pode causar o lançamento de uma SecurityException.

Se esse encadeamento estiver bloqueado em uma invocação dos métodos wait (), wait (long) ou wait (long, int) da classe Object, ou dos métodos join (), join (), join (long), join (long, int) , sleep (long) ou sleep (long, int), dessa classe, seu status de interrupção será limpo e ele receberá uma InterruptedException.

Se esse encadeamento estiver bloqueado em uma operação de E / S em um canal interruptível, o canal será fechado, o status de interrupção do encadeamento será definido e o encadeamento receberá uma ClosedByInterruptException.

Se esse encadeamento estiver bloqueado em um seletor, o status de interrupção do encadeamento será definido e retornará imediatamente da operação de seleção, possivelmente com um valor diferente de zero, como se o método de ativação do seletor fosse invocado.

Se nenhuma das condições anteriores for mantida, o status de interrupção deste encadeamento será definido.

A interrupção de um encadeamento que não está ativo não precisa ter nenhum efeito.

Lança: SecurityException - se o segmento atual não puder modificar esse segmento

Ajeet Ganga
fonte
1

Uma interrupção é uma indicação para um encadeamento de que ele deve parar o que está fazendo e fazer outra coisa. Cabe ao programador decidir exatamente como um thread responde a uma interrupção, mas é muito comum que o thread termine. Uma referência muito boa: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

Adi
fonte
1

O método Thread.interrupt () define o sinalizador interno 'status de interrupção'. Geralmente esse sinalizador é verificado pelo método Thread.interrupted ().

Por convenção, qualquer método que exista via InterruptedException precisa limpar o sinalizador de status de interrupção.

Anatoliy Shuba
fonte