Como eu faço para interromper todas as threads lançadas por uma única thread?

olá,

como eu faço isso?

Guarda as Threads num Array…

E depois quando quiser interromper, é só percorrer o Array e interromper as que quiser…

:wink:

Olá,

Utilize um ThreadGroup para agrupar estas threads e quando precisar interrompe-las, chame o metodo interrupt do ThreadGroup.

Da uma olhada no Javadoc dela.

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ThreadGroup.html

]['s

[quote=fabgp2001] Olá,

Utilize um ThreadGroup para agrupar estas threads e quando precisar interrompe-las, chame o metodo interrupt do ThreadGroup.

Da uma olhada no Javadoc dela.

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ThreadGroup.html

]['s[/quote]

Bem mais elegante :stuck_out_tongue:

alguem tem algum exemplo?

Exemplo de como criar um ThreadGroup?

É simples.

Cria uma ThreadGroup dando um nome pra ela.

ThreadGroup threadGroup = new ThreadGroup("Meu grupo de threads!");

Depois passa esse thread group para as threads que vão sendo criadas.

Runnable runnable = //Codigo aqui... Thread thread = new Thread(threadGroup, runnable); thread.start();

Depois pra interromper.

threadGroup.interrupt();

Por fim tu ainda pode ver se existe alguma thread ativa. É so da uma olhada na API e brincar com a classe. Ou ainda se precisar de algo mais complexo, olhar o pacote java.util.concurrence do Java 5.

]['s

O método interrupt não para a thread, a menos que ela seja programada para reagir a ele. Ele fará com que waits gerem interruptedException e o método Thread.isInterrupted() (caso o interrupt seja lançado fora de um wait) retorne true.

Você terá que fazer whiles do tipo:

try
{
   while (!Thread.isInterrupted() && condicao)
      wait();
}
catch (InterruptedException e)
{
   //Processa a interrupção, caso ela tenha ocorrido no wait.
}

Existe o método suspend(), que efetivamente mata a thread, mas ele foi deprecated por ser muito propenso a falhas e a gerar deadlocks.

O ideal é que os objetos por onde a thread vá percorrer estejam preparados para esse tipo de interrupção. Nesse caso, você já deve planejar de antemão o comportamento do código, para que o método run() finalize normalmente, se uma interrupção ocorrer.

O que você quer fazer, exatamente? Qual é o problema que está tentando resolver? Talvez se você descreve-lo podemos te ajudar com alguma dica.

Olá,

Pelo que sei ele até para a Thread, mas depende de varios fatores, SecurityManager, stado das threads, etc. Por isso é bom consultar a API pra não fazer besteira.

]['s

Ok, aqui vai um exemplo. Usei o interrupted e o ThreadGroup, conforme sugerido. Note que o tratamento do interrupt agora passa a ser consciente e desejado.

Outra forma de fazer isso é, ao invés de utilizar o interrupt, criar métodos no seu runnable e atributos de controle. Por exemplo, você poderia criar um atributo private volatile boolean naoMorreu = true, substituir o while por:

while (naoMorreu) { //Ao invés de Thread.interrupted()
   //Do something
}

E depois fazer o metodo

public void matar() {
   naoMorreu = false;
}

Ainda assim, você ainda teria que se incomodar com a InterruptedException.

Entretanto, essa técnica é usual. Mais até do que usar o interrupt. Mesmo quando te impossibilitando usar o thread group diretamente.

No lugar do ThreadGroup, você passa a depender de uma lista - nesse caso, fazendo um for e chamando o método matar().

Escolha o que achar melhor! :wink:

Tu chegou a testar o código?

Depois de um tempinho…

[quote]ViniGodoy
eduveks
renatotn7
fabgp2001
Thread com texto ViniGodoy finalizada.
Thread com texto fabgp2001 finalizada.
Thread com texto renatotn7 finalizada.
Thread com texto eduveks finalizada.
[/quote]
O problema é que as thread não são interrompidas de imediato, não sei qual a regra para a parada delas, mas elas são imterrompidas depois de algum tempo.

]['s

O unico problema que eu vejo com essa tecnica do atributo “nãoMorreu” é que o programador te que controlar o que a thread esta fazendo antes de para-la.

Por exemplo eu tenho uma thread que dispara comandos com o banco de dados, imaginemos que cada thread vai fazer insert e update em lote. Se eu simplesmente parar a thread sem me preocupar com o que ela está fazendo eu posso deixar estados inconsistente no meu sistema.

Isso seria semelhante a fazer um kill no meu processo o que muitas vezes não é o desejado.

]['s

Acho que você confundiu. Esse é o problema do suspend, não do não morreu. Ter que se preocupar com a thread é bom, justamente para garantir que ela não deixe o estado inválido.

Com o atributo no seu controle, você pode rodar algum código de finalização, caso a thread saia do while, e voltar a um estado consistente. Na verdade, essa técnica e descrita e recomendada por vários autores.

Vini,

Entendi, eu só to tentando alertar para se o cara for usar qualquer uma das abordagens ele tem que pensar em tudo isso. Nao da pra simplemente finalizar a thread (dar um kill) pois isso pode trazer grandes problemas no sistema.

]['s

Testei sim.

Após a chamada do interrupt (que ocorre 15 segundos depois que o programa começa a rodar), as threads são imediatamente interrompidas. Rode o código numa execução passo-a-passo, colocando um breakpoint na MainThread (de preferência na linha com o interrupt), que você verá isso mais claramente.

Ops, foi mal, achei que vc tinha feito confusão. Então está ok, pq estamos falando a mesma língua! :wink:

Na verdade… Eu até ressaltei isso nos comentários que coloquei no Runnable Printer.

Outra coisa interessante do atributo naoMorreu é que você pode fazer algum tipo de finalização antes de interromper a Thread.

Por exemplo:

public void morra() {
   rodarPreFinalizacao(); 
   naoMorreu = false; //Finaliza mesmo;
   notify(); //Dispara os waits que podem estar parados
}

[quote=ViniGodoy]Testei sim.

Após a chamada do interrupt (que ocorre 15 segundos depois que o programa começa a rodar), as threads são imediatamente interrompidas. Rode o código numa execução passo-a-passo, colocando um breakpoint na MainThread, que você verá isso mais claramente. [/quote]

Tranquilo, eu tambem testei e elas pararam, pelo que eu tinha entendido tu falou que elas não paravam com o interrupt. O unico problema é que o cara tem que prever essa interrupcao na thread.

]['s

Pessoal sei que o tópico é “antigaço”, mas gostaria muito de perguntar a respeito do código anexado pelo ViniGodoy.

Seguinte, na classe MainThread tem um sleep para garantir que todas as threads tenham tempo suficiente para executarem até o fim.
Já na classe Printer tem um outro sleep. Sobre esse sleep é correto dizer que “ele é pra garantir ou tentar garantir que todas as thread tenham oportunidade de rodar”?

Desculpem por ressuscitar tópicos… (ainda mais hoje rsrsrsr). Mas é de extrema importância pra mim.
Obrigado a todos.

O sleep dentro da classe Printer tem dois propósitos:
a) Evitar que a thread Printer consuma 100% do processador. Se você não colocar absolutamente nenhuma chamada a yield(), wait() ou sleep() numa thread, e se sua thread faz pouco I/O, isso fatidicamente acontece;
b) Dar uma pausinha. :slight_smile:

Note também que os métodos sleep(), wait() e yield() disparam a InterruptedException(). Não seria um problema não te-los na classe Printer, pois o while também testa por !Thread.interrupted(). Mas a Exception é geralmente a forma mais comum de uma thread ser interrompida, por isso, é relevante nesse exemplo. Muita gente tem a mania de “engolir” essa exceção e manter a thread dentro do while, o que a torna muito difícil de ser interrompida.

Vale ressaltar que encerrar uma thread passa a ser um procedimento cooperativo, você avisa a thread sobre sua intenção de interrompe-la, e nela coloca o código para tratar a interrupção.
Outro detalhe, é que esses métodos de encerrar uma thread funcionam na maioria dos casos mas não em 100%, por exemplo, quando a thread está bloqueada em um método que não responde à interrupção.

[quote=ViniGodoy]O sleep dentro da classe Printer tem dois propósitos:
a) Evitar que a thread Printer consuma 100% do processador. Se você não colocar absolutamente nenhuma chamada a yield(), wait() ou sleep() numa thread, e se sua thread faz pouco I/O, isso fatidicamente acontece;
b) Dar uma pausinha. :slight_smile:

Note também que os métodos sleep(), wait() e yield() disparam a InterruptedException(). Não seria um problema não te-los na classe Printer, pois o while também testa por !Thread.interrupted(). Mas a Exception é geralmente a forma mais comum de uma thread ser interrompida, por isso, é relevante nesse exemplo. Muita gente tem a mania de “engolir” essa exceção e manter a thread dentro do while, o que a torna muito difícil de ser interrompida. [/quote]

Muito obrigado!