Thread

21 respostas
N
Fala ai galera

Toda vez que eu aperto um botão na aplicação eu gero um thread

Ft ff = new Ft();

ff.start();

O problema é que se uma pessoa ficar apertando o botão varias vezes irá gerar um monte de thread e fazer a mesma coisa diversas vezes.Nem acabou a execução da primeira thread e a segunda, terceira ja começou  tmabém.Eu quero que um thread  possa ser gerado uma vez e que possa ser gerado de novo somente depois de ter acabado a anterior.Uma especie de fila para gerar thread.OU enquanto a thread estiver sendo executada nenhuma outra thread podera ser gerada.

Espero ter sido claro.

Valeu!!

21 Respostas

E

A maneira mais estúpida é desabilitar esse tal botão, e quando a thread acabar, o botão ser novamente habilitado. Que tal?

ViniGodoy

Estúpida e bastante eficaz, diga-se de passagem.

N

Como posso saber quando a thread acabou (o tempo de execução da thread podera variar) sem travar a aplicação com um loop por ex?
O inicio sabemos start();

Valeu…

E

De novo, a forma mais simples de saber se a thread acabou é ela mesmo avisar que acabou (ou seja, você pode deixar a encargo da thread reabilitar o botão. )

G

Olá amigo,
a thread é finlizada após a última linha do método run() ser executada, porém vc ainda tem o objeto (ff) ativo no heap (ou seja, pode utilizar seus atributos e métodos).

Para verificar se o método run já foi executado, você pode fazer uma flag:

Crie uma variável de instância

boolean emExecucao = false;

no início do método start

boolean emExecucao = true;

no fim do método run

boolean emExecucao = false;

no click do botão vc insere

if(!ff.emExecucao){ ff = new Ft(); ff.start(); }else{ System.out.println("Já existe uma thread em execução..."); }

Pra esse código funcionar, você precisa criar todas as Threads usando a variável “Ft ff”, se for possível torne-a uma variável de instância.

Abs.

renamed

Se essa Thread precisa ser única, Singleton não pode ser uma opção?

tralsl

se vc não quiser que seu controle fique “junto e misturado”, com seu código de Gui vc pode iniciar uma classe (que implementa Runnable)
que executa as threads adicionadas em uma fila.

imagine que vc tem apenas uma instancia da fila

Fila fifo = new Fila();

a ação do seu botão é apenas adicionar novas threads a essa fila:

syncronized(fifo){ fifo.add(new Ft()); } fifo.notify();
e vc deve instanciar uma nova thread com o método run() parecido com isso

public void run() { while (true){ Runnable r; synchronized (fifo) { //se a fila está vazia, espera if (fifo.isEmpty()) { try { fifo.wait(); } catch (InterruptedException ex) { ex.printStackTrace(); } } r = fifo.proximaTarefa(); } r.run(); } }

G

Noooosa…
Relaxa cara, depois ele refatora.

E esse seu código não vai consumir muito mais recursos do sistema do que simplesmente desabilitar o botão?

tralsl

gervas-IO:
Noooosa…
Relaxa cara, depois ele refatora.

E esse seu código não vai consumir muito mais recursos do sistema do que simplesmente desabilitar o botão?

sim, consome mais recursos, mas ele não disse que esses eram escassos

e ninguém gosta de ficar olhando um jbutton pra ver quando ele será habilitado

dessa forma ele pode apertar o botão quantas vezes quiser

mas isso não quer dizer que seja mais correto que a outra opção, depende do objetivo

mas eu achei mais OO :lol:

ViniGodoy

Ainda acho mais fácil, rápida e viável a solução que o Entaglement falou.

Aí na última linha dele, você faz:

seuBotao.setEnabled(true);

A fila só faria sentido se, para cada pressionar de botão, ele quisesse um processamento.

marcelo.bellissimo

Além do que o Vini falou, acho mais intuitivo pro usuário desabilitar o botão, fica mais do que claro que o botão realmente está fazendo alguma coisa, e ele só vai ser habilitado novamente quando o processamento acabar…

Se imagine no lugar do usuário, clicando duzentas vezes no mesmo botão e não sabendo se ele está fazendo algo ou não?

N
O botão que estou apertando esta em uma classe.

O thread esta em outra classe Ft();

A variavel (ff.variavel) da classe Ft() que eu utilizo  para controlar se esta ou não na thread if(ff.variavel==x) é resetada toda vez que eu aperto o botão.Cada objeto ff que é criado possui sua variavel com valor inicial ou resetado.

Ft ff = new Ft();

ff.start();

Se eu criar o objeto (Ft ff = new Ft():wink: como sendo global(logo abaixo da declaração da classe) esse objeto guarda certo a variavel (ff.variavel) sem resetar.Quando eu apertar o botão inicia a thread (ff.start();), só que a thread funcionar uma vez e na proxima da pau.

Não sei se fui claro…

ViniGodoy

Você tem duas opções.

A primeira, mais acoplada, menos elegante, mas mais fácil de implementar é passar o botão como parâmetro para seu Ft:

public class Ft extends Thread {
   private JButton botao;

   public Ft(JButton botao) {
       this.botao = botao;
   }

   public void run() {
       botao.setEnabled(false);
       //Faz o que tem que fazer
       botao.setEnabled(true);
   }
}

A segunda, seria criar uma interface FtListener. E fazer com que Ft receba um listener. Então, o formulário implementaria esse listener, e desabilitaria o botão. No fundo, isso é uma implementação simples do padrão Observer.

FtListener.java
public interface FtListener {
    void onExit();
}
Ft.java
public class Ft extends Thread {
   private FtListener listener;

   public Ft(JButton botao) {
       this.listener= listener;
   }

   public void run() {
       //Faz o que tem que fazer

       //Informa o listener que terminou
       listener.onExit();
   }
}
ClasseQueChamaAThread.java
botao.setEnabled(false);
Ft ff = new Ft(new FtListener() {
   public void onExit() {
      botao.setEnabled(true); 
   });
ff.start();
N

Ao apertar o botão podemos ter dois caso:

1-Ft ff = new Ft();
ff.start();

2-ff.start();

No primeiro a variavel que controla a thread ff.variavel é resetada para cada objeto ff criado e com isso não consigo fazer o controle.
No segundo caso o objeto ff
Ft ff = new Ft();
tem que ser criado logo no inicio da classe (global) e a thread só funciona a primeira vez que aperta o botão, depois da pau.

ViniGodoy

Você não pode chamar start() duas vezes no mesmo objeto Thread. Esqueça a idéia da variável global. E siga a dica que passei ali em cima.

Em ambas, o botão é desabilitado e só será reabilitado depois que a thread terminar.

N

O botão esta na classe que chama a thread

public class Botao extends javax.swing.JFrame {

portanto não consigo alterar o estado do botao na classe da thread.

public void run() {

botao.setEnabled(false);

//Faz o que tem que fazer

botao.setEnabled(true);

}

Acho que meu principal problema ainda esta em determinar o momento que a thread acaba.

N

Tem outro problema
private JButton botao;
não da pois a classe que esta usando estende extends Thread …Ta falando que não encontra o simbolo JButton

Valeu…

ViniGodoy

Você fez o import do JButton?

import javax.swing.JButton;
N

Agora deu certo mas o problema é que o botão fica inutil durante toda a thread e os outros eventos associados ao mesmo botão tb.
O botão que gera a thread tem outras funcionalidades que não podem deixar de existir enquanto a thread é exucutada e minha thread podera demorar…

N

Ao invés de eu mudar o estado do botão eu não poderia mudar o valor de uma variavel da classe que chamou a thread?

E

Ou seja, usar uma flag? É só tomar cuidado - por exemplo, essa tal flag deve ser declarada com “volatile” se você souber que essa flag pode ser acessada por 2 ou mais threads do seu programa (a thread principal do Swing também conta como thread).

Criado 10 de junho de 2010
Ultima resposta 10 de jun. de 2010
Respostas 21
Participantes 7