собственный тайм-аут Процесса Java

Вот пример:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def self.up
    rename_table :old_table_name, :new_table_name
  end

  def self.down
    rename_table :new_table_name, :old_table_name
  end
end

я должен был пойти и переименовать образцовый файл объявления вручную.

Редактирование:

В направляющих 3,1 & 4, ActiveRecord::Migration::CommandRecorder знает, как инвертировать rename_table миграции, таким образом, можно сделать это:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def change
    rename_table :old_table_name, :new_table_name
  end 
end

(Все еще необходимо пройти и вручную переименовать файлы.)

44
задан deltanovember 7 August 2009 в 23:06
поделиться

5 ответов

Вот как это делает Plexus CommandlineUtils:

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;
    }
}
19
ответ дан 26 November 2019 в 21:53
поделиться

Все остальные ответы верны, но их можно сделать более надежными и эффективными с помощью FutureTask.

Например,

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<Integer>() {
        public Integer call() throws Exception {
            java.lang.Process process = Runtime.getRuntime().exec(command); 
            return process.waitFor();
        }
    }, timeout, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    // Handle timeout here
}

Если вы делаете это неоднократно, пул потоков будет более эффективным, поскольку он кэширует потоки.

52
ответ дан 26 November 2019 в 21:53
поделиться

Вам понадобится поток, который прерывает поток, который вызывает .waitFor (); Чтобы сделать его надежным, потребуется некоторая нетривиальная синхронизация, но основные моменты таковы:

TimeoutThread:

 Thread.sleep(timeout);
 processThread.interrupt();

ProcessThread:

  try {
      proc.waitFor(); 
    } catch (InterruptedException e) {
       proc.destroy();
    }
2
ответ дан 26 November 2019 в 21:53
поделиться

Как насчет 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();
            }
        }
    }
}
6
ответ дан 26 November 2019 в 21:53
поделиться

просто немного изменил в соответствии с моими требованиями. тайм-аут здесь 10 секунд. процесс уничтожается через 10 секунд, если он не завершается.

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;  
    }  
}  
4
ответ дан 26 November 2019 в 21:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: