Temporizador

Boa tarde a todos!

Estou com o seguinte problema, tenho que desenvolver um programa que colete dados de um equipamento e o programa irá coletar os dados de tempo em tempo, o programa executará uma interface onde se possui 2 jButtons(Iniciar e Parar).

Estou usando esse trecho de código para executar de tempo em tempo:

while(…){

    // TEMPORIZADOR DE 1 SEGUNDO
    Thread t = new Thread(new Runnable() {
        public void run() {
            // temporizador
        }
    });
    try {
        //executa código
        t.sleep(2000);           
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }

}

o problema é o seguinte, ao clicar no botão iniciar ele executará esse trecho de código, mas se tiver dentro do while, o programa não irá liberar o botão parar para quando o usuário tentar parar o programa, pensei em algumas saídas mas nada que fique legal.

Qualquer ajuda será bem vinda!

Grande abraço.

Amigo… da uma olhada nessa pagina que tmb fikei com duvidas sobre esse assunto…
ve se te ajuda em algo =)
valeus

http://www.guj.com.br/posts/list/63746.java

Faça o seguinte:

[code]public class DataCollector implements Runnable {
private volatile boolean rodando = true;

public synchronized void pause() throws InterruptedException{
this.wait(1000);
}

public void run() {
try {
while (rodando) {
pause();
//Faz a leitura do equipamento
}
} catch (InterruptedException e) {
throw new RuntimeException(“Leitor de dados interrompido!”, e);
}
}

public synchronized void parar() {
    rodando = false;
    this.notifyAll();
}

}[/code]

Crie uma propriedade Data Collector no seu JFrame:

DataCollector collector = new DataCollector();

Depois no actionListener do seu botão iniciar:

new Thread(collector).start(); btnIniciar.setEnabled(false); btnParar.setEnabled(true);

E no action listener do seu botão de fechar:

collector.parar(); btnIniciar.setEnabled(true); btnParar.setEnabled(false);

Legal seu exemplo ViniGodoy!
você pode me explicar o que significa essa declaração, mais especificamente o “volatile”

private volatile boolean rodando = true;

Obrigado.

Todas as threads implementam um mecanismo de cache de variáveis, para otimizar o código e maximizar o paralelismo.

Mas isso também representa um risco. Suponha que uma thread A atualize o valor de rodando para false. A thread B, que usa esse valor, consulta o valor que está em cache, que ainda está valendo true. E não podemos prever quanto tempo leva para que a thread B renove o seu cache. Bem… esse não é um comportamento desejável, concorda?

Existem duas maneiras de prevenir isso.

  1. Declarar a variavel como volatile. Nesse caso você está dizendo para o Java: “Esqueça os caches para essa variável”. Isso tem uma pequena penalidade em performance.

  2. Apenas usar a variável em trechos de código sincronizados. Sempre que uma thread entra num trecho sincronizado, ela usa os valores mais atuais possíveis das variáveis que estão dentro desse trecho.

No caso do exemplo que eu postei, o while não está num trecho sincronizado, mas consulta o valor de rodando. Portanto, a variável foi declarada como volatile.

Ótimo ViniGodoy, essa eu não conhecia muito obrigado pela dica, funcionou perfeitamente.

Abraço.

Legal ViniGodoy!

Obrigado!

Só mais uma dica.

Eu não sei o quão sensível é o seu hardware, mas o wait está sujeito a acordar sozinho de vez enquando (spurious wakeup), antes mesmo do seu timeout de 1 segundo ter passado. É raro, mas pode acontecer.

Se isso não for um problema, deixe o código como está. Mas se for sério, você pode alterar o código com o wait para que ele fique dentro de um while, que controla o tempo:

[code]
public synchronized void pause() throws InterruptedException
{
final long finalTime = System.currentTimeMillis() + 1000;
long remaining = 1000;

while (rodando && remaining > 0) {
wait(remaining);
remaining = finalTime - System.currentTimeMillis();
}
}[/code]

Aqui no meu caso acabo usando códigos como esse, pois faço aplicações que rodam milhares de testes numa central telefônica, onde cada um desses testes faz 2 ou 3 verificações de timeout. Uma falha em falso pode significar um usuário irritado, que teve de retestar quando não havia problema nenhum (fora que isso tem uma imagem muito negativa na confiabilidade do sistema).

Mais uma coisa. Você também pode testar se o interrupt() foi usado num lugar fora do wait (onde, nesse caso, nenhuma InterruptedException é lançada). Geralmente, quando vc usa uma variável de controle como a "rodando" isso não é necessário, pois a VM só vai dar um interrupt() quando a própria VM estiver sendo finalizada. Mas só para você saber que é possível e como se faz:

while (rodando && !Thread.isInterrupted()) { ... }

Havia a idéia de se controlar o início/fim de threads com o interrupt(), que é um método da classe thread, quando o java começou. Mas essa prática parou de ser recomendada. Nunca pesquisei o motivo, mas eu gosto do fato de saber que um interrupt só vai acontecer numa thread por uma razão mais catastrófica, fora do meu próprio controle. Além disso, creio que é uma boa política separar o mecanismo de controle de uma thread (sua classe Runnable) do mecanismo de execução da thread em si (a classe Thread ou a classe ExecutorService).

caramba!!!

Todos os seus posts sobre Threads são aulas completas. Já dá pra montar um tutorial pro GUJ.

Parabéns Cara!

Saudações

A gente faz o que pode. :wink:

[quote]
ViniGodoy [/quote]

Lembra de um post que você me ajudo a resolver um problema do swing, então estou estudando threads() e necessito uma ajuda, estou montando o um sistema de envio de newsletter e estou montando a fila, e como alguns exemplos criei minhas classes de envio de email extends Thread, e implementei, agora eu estou com uma baita dúvida, eu necessito enviar filas de 25 emails por hora, como consigo fazer este controle? No meu SW eu listo na Jtable a lista de empresas para quais devo enviar, são em média 200 emails por dia, no envio de email existem 2 tipos um com anexo padrão do gmail e outro que tem de aparecer no corpo do email, então fiz duas classes usando a API Commons mail uma com o MultiPartemail e outra com HtmlEmail, da lista que está no jtable crio duas sub-listas sendo 1 para envio com anexo tipo gmail e outra com anexo no corpo.

Eu tentei gerenciar o envio de 25 emails dentro do laço while para quando meu i chegar a 25 acionar o thread.sleep(300000); e depois iniciar o envio de mais 25, porém não está funcionando e ele somente está enviando para 1 email da lista( criei 5 emails no yahoo para teste), poderia me ajudar já to ficando com uma baita dor de cabeça com isso. Valei

Use o Quartz.

Quartz, ainda não conheço, como funciona grato

É um agendador de tarefas em Java, dos bons.

Dá uma lida aqui:

E pesquise aqui mesmo no GUJ que tem muita coisa.