Dúvida com thread e TimerTask

1 resposta
R

Boa Tarde, gostaria de um help e sugestões para resolução do seguinte problema:
Eu tenho uma tela em swing onde o usuário preenche alguns campos e ao clicar no botão é startado um processo que realiza uma série de cálculos para as filiais da empresa. Como esse processo estava muito lento e fazia muito acesso a banco de dados, eu criei uma classe seguindo o pattern Observer que utiliza uma TimerTask e cria um pool de Threads para executar esse cálculo concorrentemente para cada filial, já que são 160 filiais e não daria para ficar calculando seqüencialmente.
Bom até aí tudo bem, o programa melhorou considerávelmente a performance, porém quando o usuário clica no botão para realizar o cálculo, eu desabilito o botão e todos os campos da tela. Só que eu não estou conseguindo bolar uma maneira para que ao término da execução do cálculo seja enviada uma mensagem ao usuário informando que o processo já foi encerrado.
Abaixo está o código:

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

public class Observer 
{
	private long lastHeartBeat;
	private Vector filiais;
	private Timer timer;
	private Execucao execucao;
	private static Observer instance;
	private long timeOut;
	
	public synchronized void setLastHeartBeat(long lastHeartBeat)
	{
		this.lastHeartBeat = lastHeartBeat;
	}

	public synchronized long getLastHeartBeat()
	{
		return lastHeartBeat;
	}
	
	private Observer()
	{  
        	timeOut = 600000;
	}

	public static Observer getInstance()
	{
		if (instance == null)
		{
			instance = new Observer();
		}
		return instance;
	}
	
	
	public Execucao getExecucao()
	{
		return execucao;
	}

	public void setExecucao(Execucao execucao)
	{
		this.execucao = execucao;
	}

	public void stopObservation(){
		filiais = null;
	}
	
	public void startObservation(Vector filiaisParaCalculo) throws ObserverException
	{
		setLastHeartBeat(0);
		filiais = filiaisParaCalculo;
		timer = new Timer();
		TimerTask task = new TimerTask()
		{
			// Thread de observacao de execucao
			// caso a execucao esteja travada, 
			public void run()
			{
				//System.out.println("getLastHeartBeat() = " + getLastHeartBeat());
				//System.out.println("Observer: antes da execucao");
				if (getLastHeartBeat() + timeOut < System.currentTimeMillis())
				{
					System.out.println("[" + new Date() + "] - Iniciando execução.");
					if (execucao == null)
					{
						System.out.println("[" + new Date() + "] - Executando");
						execucao = new Execucao(filiais);
						execucao.start();
					}
					else
					{
						System.out.println("[" + new Date() + "] - Parando execução anterior.");
						execucao.stopExecution();
						System.out.println("[" + new Date() + "] - Reiniciando execução por timeout.");
						if (filiais != null){
							execucao = new Execucao(filiais);
							execucao.start();
						}else{
							timer.cancel();
						}
					}
				}
				else
				{
					// nao deu timeout, mas a execucao já pode ter finalizado, 
					// reniciar execucao neste caso
					if (execucao != null)
					{
						if (execucao.isTerminated())
						{
							System.out.println("[" + new Date() + "] - Execução terminada, reiniciando.");
							execucao = new Execucao(filiais);
							execucao.start();
						}
					}
				}
				//System.out.println("Observer: depois da execucao");
			}
		};
		timer.schedule(task,new java.util.Date(), 10000);
		if (filiais == null){
			throw new ObserverException("Erro");
		}
	}
}
A classe Execucao, cria um pool de Threads que chama a classe responsável pela execução do cálculo. Este método startObservation é chamado assim que o usuário clica no botão. Eu tentei fazer com que o método disparasse uma exception quando o processo tivesse terminado, assim eu a trataria no evento do botão e enviaria a mensagem ao usuário, porèm isso não deu certo já que usando o Timer, as TimerTasks são executadas em Threads separadas e ao passar no if (filiais == null) o vetor contém elementos e a tela fica presa. Agradeço desde já a ajuda.

1 Resposta

sergiotaborda

Eu não consigo ver onde vc usou o padrão observer, mas deixe que lhe diga o seguinte:

Vc precisa de um objecto que recebe eventos. Quando uma tarefa termina ela usa o evento para informar esse objecto
que terminou. Quando todas tiverem terminado, o processo está pronto.
Por outro lado vc não precisa de Timer ou Timetask, apenas Runnable e/ou Thread

class TaskObserver {

   
  
    public void onTaskTerminated() {
          terminated++;

           if (terminated == NumeroMáximoDeTarefas) {
                 this.notifyAll(); // sinaliza que pode deixar de esperar
          } 
   }

   public void start () {
         terminated = 0;

          for (int i =0 ; i < NumeroMáximoDeTarefas;i++){
                   TaskExecutorThread tet = new TaskExecutorThread (this);
                    tet.start();
         }

         this.wait(); // espera até terminar todo o mundo
   }


}


class TaskExecutorThread  extends Thread {
 
    private TaskObserver observer
    TaskExecutorThread  (TaskObserver  observer){
          this.observer = observer;
    }

     public void run(){
           // faz calculos

          observer.onTaskTerminated();
     }

}

Em Java 6 existem as classes Executor , Queue e Future que podem ser usadas para deixar o codigo melhor e mais simples
de entender. Se puder usar Java 6 dê uma olhadan elas

Criado 25 de agosto de 2007
Ultima resposta 25 de ago. de 2007
Respostas 1
Participantes 2