Tô implementando um sistema que lê informações de uma página da web e as grava numa base de dados local. No entanto, esse processo pode ser muito de demorado e, na minha aplicação, eu dou ao usuário a opção de interromper o processo no meio da execução. O problema disso é que eu não tinha como parar o processo do nada, daí, toda vez que encerrava o processo gerava uma exceção.
Para resolver isso, passei a utilizar Threads. Agora, para encerrar o processo, eu uso o método stop(). Isso me leva à primeira pergunta:
A documentação me diz que o método stop() está superado e que ele é perigoso. Mas, se eu utilizo threads com o único fim de poder encerrar o processo quando eu quiser, qual método devo utilizar/sobrescrever para garantir uma saída limpa?
O uso de threads me levou a um outro problema… Todos os métodos do meu importador lançam as exceções para o método chamador sem tratá-las. Esse tratamento de exceções eu fazia na minha interface gráfica, mostrando mensagens ao usuário e tomando atitudes. O problema é que, ao encapsular parte da minha lógica numa Thread, eu fico obrigado a tratar as exceções dentro do método run(), já que ele não lança exceções. Tentei inclusive pegar as exceções dentro do método e lançar uma RuntimeException, no entanto, esse tipo de exceção não pode ser capturada. Assim, minha segunda pergunta é:
Como eu faço para lançar uma exceção de dentro de uma thread, de modo que eu possa capturá-la fora da thread?
Quanto ao stop o que é recomendado é que você crie seu método de parada como no exemplo abaixo.
public class MeuProcesso implements Runnable {
private boolean cancelado;
public void run() {
while (!cancelado) {
// Fica executando aqui
}
}
public void cancelarProcesso() {
cancelado = true;
}
}
Agora você tem que ver dentro da sua implementação como usar a mesma lógica para parar seu thread.
Quanto a questão das exceptions você pode usar algo como uma pattern Observable para capturar a exception dentro do thread e redirecionar para alguma tela da sua aplicação.
Cuidado. Como a variável cancelado será acessada por duas Threads, ela deve ser declarada como volatile ou sempre ser usada dentro de um bloco sincronizado.
Além do método que o colega descreveu, procure também tratar corretamente a InterruptedException, fazendo que sua thread pare sempre que receber uma interrupção dessas.
Então porque não usam a infraestrutura do Executor? Ou Future? Eles tem mecanismos mais inteligentes para Stop ou cancelamento de threads. Na verdade essa que é a abordagem indicada…
É… confesso que é meio complexo… Dá uma olhada na API para entender melhor… Mas nada mais é do que passar um Runnable para o Executor e startar o Executor… Se der tempo mais tarde (depois do experiente) eu posto aqui algum exemplo…
[quote=ViniGodoy][quote=kaoe]
Bom, vamos por partes.
Quanto ao stop o que é recomendado é que você crie seu método de parada como no exemplo abaixo.
…
[/quote]
Cuidado. Como a variável cancelado será acessada por duas Threads, ela deve ser declarada como volatile ou sempre ser usada dentro de um bloco sincronizado.
Além do método que o colega descreveu, procure também tratar corretamente a InterruptedException, fazendo que sua thread pare sempre que receber uma interrupção dessas.[/quote]
O que nos leva a concluir que o jeito certo de parar uma thread é chamando thread.interrupt();
Isso de condição de paragem é quando existe uma logica de paragem. no caso aqui existe a ação especifica de parar a thread e isso é feito com interrupt.