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:
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.
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
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.