Thread

10 respostas
P

Tenho um sistema onde evoco o jframe no static main,
porêm fiz uma thread para pegar os clicks do mouse e do teclado,

estarto a thread e executa uma primeira vez com o click, se a condição que eu desejo não for verdadeira, espera o próximo click, mas para isso, gostaria que a thread pausasse, em um determinado periodo para não ficar executando todas as vezes que clicasse,
tentei com sleep e wait, wait não funcionou, com o sleep, todo o sistema para no tempo determinado, e não somente a thread que fiz,

ja tentei com o (nome da thread).sleep(), Thread.sleep(), mas para todo o projeto.

Alguém tem alguma ideia que possa me ajudar?
obrigado!

10 Respostas

M

Como está essa Thread que captura eventos?

P

Em uma determinada tela:

TimeOut out = new TimeOut();
            out.setEmpresa(beanEmpresa.getCodigo());
            Thread t = new Thread(out);
            t.start();

Dentro da classe TimeOut que extende Thread:

public void run() {
        try {
            trackSystemEvents();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "ERRO_TimeOut: " + ex,
                    "INLOC SISTEMAS", JOptionPane.INFORMATION_MESSAGE);
        }
    }



private void trackSystemEvents() throws Exception {
        PdvNegocio pdvNegocio = new PdvNegocio();
        dados = (DadosConfiguracaoModuloPdv) pdvNegocio.procurar(empresa, new Conexao());

        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {

            public void eventDispatched(AWTEvent event) {
                String eventText = event.toString();
                if (eventText.indexOf("PRESSED") != -1 || eventText.indexOf("RELEASED") != -1) {
                    if (velho == 0) {
                        velho = new Date().getTime();
                    } else {
                        if ((new Date().getTime() - velho) > ((dados.getOcioso() * 60) * 1000)) {
                            JOptionPane.showMessageDialog(null, "A sessão foi expirada, o sistema será encerrado!",
                                    "INLOC SISTEMAS", JOptionPane.INFORMATION_MESSAGE);
                            System.exit(0);
                        } else {
                            velho = new Date().getTime();
                        }
                    }
                }
            }
        }, AWTEvent.MOUSE_EVENT_MASK + AWTEvent.KEY_EVENT_MASK);
    }
ViniGodoy
a. Você não precisa de uma thread;

b. Sua thread extra irá finalizar após o método trackSystemEvents ser chamado;

c. Você pode usar o método contains no lugar do indexOf() != -1

d. Já experimentou colocar um breakpoint na primera linha listener (linha 19 do código postado por você) ?

e. Também é bom seguir a documentação:

Logo seu parâmetro fica:
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.KEY_EVENT_MASK;
(matematicamente, os dois geralmente são equivalentes).
f. E tem essa nota também:

ViniGodoy

Sua thread de timeout deveria ser mais ou menos assim:

public class TimeOut implements Runnable {
    private static final long INTERVALO = 1000; //Verifica de 1 em 1 segundo

    private volatile long ultimoEvento;
    private long maxTempoOcioso;

    public TimeOut(long maxTempoOcioso) {
       this.maxTempoOcioso = maxTempoOcioso;
    }

    public void run() {
        ultimoEvento= System.currentTimeMillis();
        try {           
           while(System.currentTimeMillis() - ultimoEvento < maxTempoOcioso) {
               Thread.sleep(INTERVALO);                          
           } 
           JOptionPane.showMessageDialog(null, "A sessão foi expirada, o sistema será encerrado!", 
               "INLOC SISTEMAS", OptionPane.INFORMATION_MESSAGE);  
           System.exit(0);          
        }
        catch (InterruptedException e) {}
    }

    public void notificarEvento() 
    {
        ultimoEvento = System.currentTimeMillis();
    }
}
Essa thread somente verifica se houve algum evento. Se não houve, aborta o sistema. Você deve então disparar essa thread, e registrar o AWTListener para chamar o método notificarEvento:
final TimeOut timeout = new TimeOut(dados.getOcioso() * 60) * 1000);

Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {  
   public void eventDispatched(AWTEvent event) {  
      String eventText = event.toString();
      if (eventText.contains("PRESSED") || eventText.contains("RELEASED")) {
         timeout.notificarEvento();
      }
   }
}, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.KEY_EVENT_MASK);

Thread t = new Thread(timeout);
t.setName("Timeout thread");
t.setDaemon(true);
t.start();

O que acontece então? A thread TimeOut verifica de segundo em segundo se o tempo máximo já expirou. Caso tenha expirado, aborta o sistema.
Porém o seu listener da awt irá avisar essa thread que um evento chegou, zerando a contagem de tempo.

P

obrigado pela dicas das melhorias, vou estudar mais o que você disse e fazê-las

mas a thread nunca está sendo finalizada, executa em todos os clicks de mouse e teclado, é pra ser assim mesmo, mas eu queria dar um tempo, para não ficar chamando este método a todo momento, tipo dar um sleep e voltar a verificar, tempos depois.

mexi em tantas coisas aqui agora, que começou a dar problema, quando abre o JOptionPane para dar ok com a mensagem, clico, ele ve o clique, e volta pro começo do método, ta dando um loop.

P

opa, respondemos ao mesmo tempo, vou ver sua mensagem anterior,
MUITO OBRIGADO.

ViniGodoy

Você está confundindo o comportamento do listener, com a execução da thread. O listener será executado sempre que um evento for gerado na AWT. Isso ocorre na própria thread do Swing.

Já aquela thread Timeout que você fez finaliza, depois que esse listener é registrado. A thread em si, não está fazendo nada, só registrando o listener. Agora, o jeito que está, você também não verificava de tempos em tempos se o timeout expirou. O que aconteceria no seu sistema é que, caso o timeout tenha expirado, o usuário só perceberia no próximo pressionar de teclas, ou na próxima movimentação do mouse.

Você realmente precisa de uma thread, mas para que ela fique verificando o tempo todo se é hora de fechar o sistema.

P

uma dúvida que estou tendo analisando o que você me disse,

eu coloquei o listener dentro da thread para ser executado de qualquer janela do sistema,

posso estar, provavelmente estou, mas pelo que entendi eu chamo o código do listener, somente onde eu starto a Thread?

Ou eu ainda vou utilizar aquele trackSystemEvents() que eu tinha, substituindo o método de evento pelo seu, em outra classe implementando o run e chamando o track?
que dae do track chama a nova thread que você me explicou, averiguando o tempo.

ViniGodoy

Sim, só quando registra a thread. Esse listener ficará ouvindo todo e qualquer evento que for gerado enquanto qualquer janela estiver aberta, independente da tela do sistema. Ele ouve a AWT inteira.

Não, aquele trackEvents não é mais necessário. Se você olhar certinho o meu código, vai ver que eu também registro o listener, como o trackEvents fazia.  separei melhor as responsabilidades:

a. Thread: Apenas verifica se o timeout acabou;

b. Listener (trackevents): Verifica se um evento chegou e, se for do tipo desejado, notifica a thread;
P

agradeço muito pela ajuda, parece que agora deu certo, minha dúvida era se funcionava em todas as telas, se o evento de outras telas iria para o listener criado, que coloquei na janela principal. Deu tudo certo, obrigado pela ajuda.!

Feliz ano novo =P =)

Criado 30 de dezembro de 2009
Ultima resposta 30 de dez. de 2009
Respostas 10
Participantes 3