Você poderia explicar o que java.lang.Thread.interrupt()
faz quando invocado?
Você poderia explicar o que java.lang.Thread.interrupt()
faz quando invocado?
Respostas:
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()
java.util.concurrent
estruturasInterruptedException
, 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.
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
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.
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;
}
}
Thread.interrupt()
define o status / sinalizador interrompido do encadeamento de destino como true que, quando marcado, Thread.interrupted()
pode ajudar a interromper o encadeamento sem fim. Consulte http://www.yegor256.com/2015/10/20/interrupted-exception.html
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 .
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
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
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.