Java longa duração tarefa da linha de interrupção vs cancelar bandeira
-
19-09-2019 - |
Pergunta
Eu tenho uma tarefa de longa duração, algo como:
public void myCancellableTask() {
while ( someCondition ) {
checkIfCancelRequested();
doSomeWork();
}
}
A tarefa pode ser cancelado (a cancelar é solicitada e checkIfCancelRequested () verifica a bandeira cancelar). Geralmente quando eu escrevo laços canceláveis ??como este, eu usar uma bandeira para indicar que um cancelamento foi solicitado. Mas, eu sei que eu também poderia usar Thread.interrupt e verificar se o segmento foi interrompido. Eu não estou certo de que seria a abordagem preferida e por quê, pensamentos?
graças,
Jeff
Solução
interrupção vai explodir o fio a partir de uma lista de condições de espera especificado. Seu próprio cancelar bandeira não vai. Se você quiser espera de interrupção no IO e eventos, utilize interrupção. Caso contrário, use o seu próprio.
Outras dicas
Um problema com o uso de interrupção é que se você não controlar todo o código que está sendo executado , você corre o risco da interrupção não trabalhando "corretamente" por causa de alguém está quebrado compreensão de como a interrupções punho em sua biblioteca. Essa é a API invisivelmente exportações uma API em torno de seu tratamento de interrupt
s que você se torna dependente.
No seu exemplo, doSomeWork
suponha que estava em um JAR 3-parte e se parece com:
public void doSomeWork() {
try {
api.callAndWaitAnswer() ;
}
catch (InterruptedException e) { throw new AssertionError(); }
}
Agora você tem que lidar com um AssertionError
(ou qualquer outra coisa que a biblioteca que você está usando pode lançar). Eu vi desenvolvedores experientes jogar todos os tipos de absurdo em receber interrupções! Por outro lado, talvez o método ficou assim:
public void doSomeWork() {
while (true) {
try {
return api.callAndWaitAnswer() ;
}
catch (InterruptedException e) { /* retry! */ }
}
}
Esta "manipulação imprópria" de interrupção faz com que seu programa para repetir indefinidamente. Novamente, não descartar essa tão ridículo; há um monte de quebrada interrupção manipulação mecanismos lá fora.
Pelo menos usando sua própria bandeira será completamente invisível para quaisquer bibliotecas 3rd-party.
Depende da implementação doSomeWork()
. É que a computação puro ou o faz (em qualquer ponto) envolvem bloqueio de API (como IO) chamadas? Por O bmargulies resposta, muitas APIs de bloqueio em JDK são interruptível e irá propagar a exceção interrompido até a pilha.
Assim, se o trabalho envolve potencialmente bloqueando atividades, você need'll tomar interrupções em consideração mesmo se você decide para controlar o processo de utilização de uma bandeira, e deve apropriadamente pegar e tratar / propagar a interrupções.
Além disso, se depender de uma bandeira, certificar-se de sua bandeira é declarado com a semântica volatile
.
Eu acho que é uma questão de preferência na maioria dos casos. Pessoalmente eu gostaria de ir para a bandeira feitos à mão. Ele lhe dá mais controle - por exemplo, desta forma você certificar-se de que o seu segmento não deixar algum outro objeto em um estado inconsistente. Além disso, se o desempenho é realmente crítico, tenha em mente que o uso de exceções tem uma sobrecarga (mesmo que seja insignificante em 99% dos casos).