Tempo de execução de um programa externo - a revolta das threads

Pessoal,

Tenho uma classe (logo abaixo). Que executa programas externos ao java, eu a chamo da seguinte forma (em outra classe):

Executa execu = new Executa();
int exe = execu.executa("c:/windows/notepad.exe", "Felipe", "123");
execu.executa("C:/WINDOWS/system32/calc.exe", "Felipe", "123");

Bom, a chamda é executada na boa…ou seja, os programas são abertos e é salvo no banco qual programa foi executado.

Qual o meu problema ???
Preciso saber qt tempo esse programa ficou aberto pelo usuário. Tipo o cara pode chamar a calculadora e o notepad. Preciso saber qt tempo cada um deles ficou aberto. O que está ocorrendo é que está sendo salvo no banco sempre um tempo fixo para o primeiro a ser chamado, exemplo:

descricao tempo


c:/windows/notepad.exe 16
C:/WINDOWS/system32/calc.exe 0

package com.tcc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;

public class Executa {
	
	public Executa () throws IOException, InterruptedException {
		super();
	}	
	
	public int executa(final String caminhoPrograma, String usuario, String senha) throws IOException, InterruptedException, InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException{
		
		final Process p = Runtime.getRuntime().exec(caminhoPrograma);
		
		final Monitora monit = new Monitora(usuario, senha);	
		monit.setDescricao(caminhoPrograma);
		
		// ARMAZENA O INICIO DA EXECUCAO DO PROGRAMA
		long inicioTempoMs = System.currentTimeMillis();
		
		new Thread(){
			public void run(){
				try{
					BufferedReader in = new BufferedReader(new InputStreamReader (p.getInputStream()));
					  String str = null;
					  while ( (str = in.readLine()) != null )
						  System.out.println(str);
					  monit.setSaida(str);
					  in.close();
				}catch (IOException e){
					e.printStackTrace();
				}
		    }
		}.start();    
		
		new Thread(){
			public void run(){
				try{
					BufferedReader in = new BufferedReader(new InputStreamReader (p.getErrorStream()));
					  String str = null;
					  while ( (str = in.readLine()) != null )
					    System.out.println(str);
					  monit.setErro(str);
					  in.close();					
				}catch (IOException e){
					e.printStackTrace();
				}
		    }
			
		}.start();
		
		// GRAVA O TEMPO EM QUE O PROGRAMA FICOU EM EXECUCAO
		Long terminoTempoMs = new Long(System.currentTimeMillis() - inicioTempoMs);		
		monit.setTempo(terminoTempoMs.toString());
		monit.gravar();	
	
		return 0;
	
	} 	
}

alguem poderia dar uma dica ?

Obrigado ! estou trabalhando em um trabalho de conclusao e como nao tenho experiencia em java estou levando surra de coisas simples.

O Notepad, Calc e outros programas, ao serem executados, não “prendem” o programa que os está chamando. Portanto o tempo registrado é sempre zero, ou algo parecido com isso.

Se quiser esperar o programa terminar, use waitFor. Entretanto, já aviso que waitFor vai “prender” o seu programa.

thingol,

Entao estou ferrado, pois preciso que mais de um programa seja executado no mesmo instante além ter o tempo de execução de cada um.

Tentei através das threads de leitura de erro e saida que isso fosse possivel, ou seja, continuar a execução do meu programa e ter uma idéia de tempo.

Obrigado !

Ora, inicie uma thread para cada programa que você quer medir, e espere dentro de cada thread com waitFor. Você nem precisa ficar examinando as streams de entrada e saída :stuck_out_tongue:

Saquei thingol,

Vou fazer uma tentativa, depois posto aqui pra turma pois pode ser de interesse de mais alguém.

Valeu !

Bom,

A dica funcionou, ou seja, agora com a nova thread o programa imprime o tempo de execucao da chamada ao programa externo.

Mas falta um detalhe, como faço para passar esse valor a classe chamadora ?

Como fazer com que na chama abaixo eu consiga dar um “getTempoExecucao” ?

		Executa execu = new Executa();
		//long inicioTempoMs = System.currentTimeMillis();		
		int exe = execu.executa("c:/windows/notepad.exe", "Felipe", "123");
		execu.executa("C:/WINDOWS/system32/calc.exe", "Felipe", "123");
package com.tcc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;

public class Executa {
	
	public Executa () throws IOException, InterruptedException {
		super();
	}	
	
	public int executa(final String caminhoPrograma, String usuario, String senha) throws IOException, InterruptedException, InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException{
		
		final Process p = Runtime.getRuntime().exec(caminhoPrograma);
		
		final Monitora monit = new Monitora(usuario, senha);	
		monit.setDescricao(caminhoPrograma);
		
		// ARMAZENA O INICIO DA EXECUCAO DO PROGRAMA
		long inicioTempoMs = System.currentTimeMillis();
		
		new Thread(){
			public void run(){
				try{
					long inicio = System.currentTimeMillis();
					p.waitFor();
//IMPRIME O TEMPO Q LEVOU PARA EXECUTAR
					System.out.println(System.currentTimeMillis() - inicio);
				}catch (InterruptedException e) {
					e.printStackTrace();
				}
		    }
		}.start(); 		
		
		new Thread(){
			public void run(){
				try{
					BufferedReader in = new BufferedReader(new InputStreamReader (p.getInputStream()));
					  String str = null;
					  while ( (str = in.readLine()) != null )
						  System.out.println(str);
					  monit.setSaida(str);
					  in.close();
				}catch (IOException e){
					e.printStackTrace();
				}
		    }
		}.start();    
		
		new Thread(){
			public void run(){
				try{
					BufferedReader in = new BufferedReader(new InputStreamReader (p.getErrorStream()));
					  String str = null;
					  while ( (str = in.readLine()) != null )
					    System.out.println(str);
					  monit.setErro(str);
					  in.close();					
				}catch (IOException e){
					e.printStackTrace();
				}
		    }
			
		}.start();
		
		// GRAVA O TEMPO EM QUE O PROGRAMA FICOU EM EXECUCAO
		Long terminoTempoMs = new Long(System.currentTimeMillis() - inicioTempoMs);		
		monit.setTempo(terminoTempoMs.toString());
		monit.gravar();	
	
		return 0;
	
	} 	
}

Você precisa esperar a thread acabar (com join) .
Em vez de criar uma thread “crua”, como você fez, crie uma thread usando uma classe que implemente Runnable, e implemente um método “getTempoExecução” nessa classe.
Aí você espera todas as threads acabarem.

oq é um join ?

Poderia dar um exemplo ?

join