47 votes

Expiration du processus Java natif

Pour le moment, j'exécute un processus natif en utilisant les éléments suivants:

 java.lang.Process process = Runtime.getRuntime().exec(command); 
int returnCode = process.waitFor();
 

Supposons qu'au lieu d'attendre le retour du programme, je souhaite terminer si un certain laps de temps s'est écoulé. Comment puis-je faire cela?

54voto

ZZ Coder Points 36990

Toutes les autres réponses sont correctes, mais FutureTask peut le rendre plus robuste et efficace.

Par exemple,

 private static final ExecutorService THREAD_POOL 
    = Executors.newCachedThreadPool();

private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit)
    throws InterruptedException, ExecutionException, TimeoutException
{
    FutureTask<T> task = new FutureTask<T>(c);
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}

try {
    int returnCode = timedCall(new Callable<int>() {
        public int call() throws Exception
        {
            java.lang.Process process = Runtime.getRuntime().exec(command); 
            return process.waitFor();
        }, timeout, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    // Handle timeout here
}
 

Si vous faites cela à plusieurs reprises, le pool de threads est plus efficace car il met en cache les threads.

25voto

Si vous utilisez Java 8, vous pouvez simplement utiliser le nouveau waitFor avec timeout :

 Process p = ...
if(!p.waitFor(1, TimeUnit.MINUTE)) {
    //timeout - kill the process. 
    p.destroy(); // consider using destroyForcibly instead
}
 

19voto

Rich Seller Points 46052

Voici comment le Plexus CommandlineUtils le fait:

 Process p;

p = cl.execute();

...

if ( timeoutInSeconds <= 0 )
{
    returnValue = p.waitFor();
}
else
{
    long now = System.currentTimeMillis();
    long timeoutInMillis = 1000L * timeoutInSeconds;
    long finish = now + timeoutInMillis;
    while ( isAlive( p ) && ( System.currentTimeMillis() < finish ) )
    {
        Thread.sleep( 10 );
    }
    if ( isAlive( p ) )
    {
        throw new InterruptedException( "Process timeout out after " + timeoutInSeconds + " seconds" );
    }
    returnValue = p.exitValue();
}

public static boolean isAlive( Process p ) {
    try
    {
        p.exitValue();
        return false;
    } catch (IllegalThreadStateException e) {
        return true;
    }
}
 

6voto

mickthompson Points 1991

Qu'en est-il de la manière Groovy

 public void yourMethod() {
    ...
    Process process = new ProcessBuilder(...).start(); 
    //wait 5 secs or kill the process
    waitForOrKill(process, TimeUnit.SECONDS.toMillis(5));
    ...
}

public static void waitForOrKill(Process self, long numberOfMillis) {
    ProcessRunner runnable = new ProcessRunner(self);
    Thread thread = new Thread(runnable);
    thread.start();
    runnable.waitForOrKill(numberOfMillis);
}

protected static class ProcessRunner implements Runnable {
    Process process;
    private boolean finished;

    public ProcessRunner(Process process) {
        this.process = process;
    }

    public void run() {
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            // Ignore
        }
        synchronized (this) {
            notifyAll();
            finished = true;
        }
    }

    public synchronized void waitForOrKill(long millis) {
        if (!finished) {
            try {
                wait(millis);
            } catch (InterruptedException e) {
                // Ignore
            }
            if (!finished) {
                process.destroy();
            }
        }
    }
}
 

4voto

nuwan Points 21

vient de modifier un peu en fonction de mes besoins. temps mort est ici 10 secondes. le processus est en train d'être détruit après 10 secondes s'il ne se termine pas.

 public static void main(String arg[])
{


    try{

    Process p =Runtime.getRuntime().exec("\"C:/Program Files/VanDyke Software/SecureCRT/SecureCRT.exe\"");
    long now = System.currentTimeMillis(); 
    long timeoutInMillis = 1000L * 10; 
    long finish = now + timeoutInMillis; 
    while ( isAlive( p ) )
    { 
        Thread.sleep( 10 ); 
        if ( System.currentTimeMillis() > finish ) {

            p.destroy();

        }



    } 

    }
    catch (Exception err) {
      err.printStackTrace();

        }
}

public static boolean isAlive( Process p ) {  
    try  
    {  
        p.exitValue();  
        return false;  
    } catch (IllegalThreadStateException e) {  
        return true;  
    }  
}  
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X