Respostas:
Isso é feito para manter o estado .
Ao capturar InterruptException
e engolir, você basicamente impede que métodos / grupos de segmentos de nível superior notem a interrupção. O que pode causar problemas.
Ao ligar Thread.currentThread().interrupt()
, você define o sinalizador de interrupção do encadeamento, para que os manipuladores de interrupção de nível mais alto notem e possam lidar com isso adequadamente.
A Concorrência Java na Prática discute isso com mais detalhes no Capítulo 7.1.3: Respondendo à interrupção . Sua regra é:
Somente o código que implementa a diretiva de interrupção de um encadeamento pode engolir uma solicitação de interrupção. O código de tarefa e biblioteca de uso geral nunca deve engolir solicitações de interrupção.
interrupt()
chamada é a única maneira de definir o sinalizador interrompido depois que você recebe uma notificação sobre esse estado por meio do outro "mecanismo de entrega" - o InterruptedException
e deseja ou não pode jogá-lo novamente.
Eu acho que esse exemplo de código deixa as coisas um pouco claras. A classe que faz o trabalho:
public class InterruptedSleepingThread extends Thread {
@Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i=0;i<Integer.MAX_VALUE;i++) {
//You are kidding me
System.out.println(i + " " + i*2);
//Let me sleep <evil grin>
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
}else {
sleepBabySleep();
}
}
}
/**
*
*/
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
A classe principal:
public class InterruptedSleepingThreadMain {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
InterruptedSleepingThread thread = new InterruptedSleepingThread();
thread.start();
//Giving 10 seconds to finish the job.
Thread.sleep(10000);
//Let me interrupt
thread.interrupt();
}
}
Tente interromper a chamada sem restaurar o status.
Nota:
Como interrompo um encadeamento que aguarda longos períodos (por exemplo, entrada)?
Para que essa técnica funcione, é essencial que qualquer método que capte uma exceção de interrupção e não esteja preparado para lidar com ela reafirme a exceção imediatamente. Dizemos reafirmações em vez de repetições, porque nem sempre é possível repetir a exceção. Se o método que captura a InterruptedException não for declarado para lançar essa exceção (marcada), ele deverá "se reinterromper" com o seguinte encantamento:
Thread.currentThread().interrupt();
Isso garante que o Thread reraise a InterruptedException assim que possível.
Eu consideraria uma prática ruim ou pelo menos um pouco arriscada. Geralmente, os métodos de nível superior não realizam operações de bloqueio e nunca serão vistos InterruptedException
lá. Se você o mascarar em todos os lugares em que executar operações interruptíveis, nunca o conseguirá.
A única lógica para Thread.currentThread.interrupt()
e não gerar nenhuma outra exceção ou solicitação de interrupção de sinalização de qualquer outra maneira (por exemplo, definir interrupted
variável variável local no loop principal de um encadeamento) é a situação em que você realmente não pode fazer nada com a exceção, como nos finally
blocos.
Veja a resposta de Péter Török, se você quiser entender melhor as implicações da Thread.currentThread.interrupt()
chamada.
Consulte java doc
Se esse encadeamento estiver bloqueado em uma chamada de wait (), join (), sleep (long), seu status de interrupção será limpo e ele receberá uma InterruptedException.
Se esse encadeamento estiver bloqueado em uma operação de E / S, 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 ele retornará imediatamente da operação de seleção.
Se nenhuma das condições anteriores for mantida, o status de interrupção deste encadeamento será definido.
Portanto, se você alterar o método sleepBabySleep () no @Ajay George Answer à operação de E / S ou apenas um sysout, não será necessário definir o status novamente para interromper o programa. (BTW, eles nem lançam InterruptedException)
Assim como @ Péter Török disse => Isso é feito para manter o estado. (Especialmente para o método que lançará InterruptedException)
InterruptedException
status de interrupção limpa quando o faz. Acho que isso torna a resposta mais clara em termos de por que você precisa preservar o status de interrupção.