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 só 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!!
Thread
21 Respostas
A maneira mais estúpida é desabilitar esse tal botão, e quando a thread acabar, o botão ser novamente habilitado. Que tal?
Estúpida e bastante eficaz, diga-se de passagem.
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…
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. )
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.
Se essa Thread precisa ser única, Singleton não pode ser uma opção?
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();
}
}
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?
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:
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.
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?
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()
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…
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.javapublic interface FtListener {
void onExit();
}
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();
}
}
botao.setEnabled(false);
Ft ff = new Ft(new FtListener() {
public void onExit() {
botao.setEnabled(true);
});
ff.start();
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.
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.
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.
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…
Você fez o import do JButton?
import javax.swing.JButton;
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…
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?
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).