2012-01-24 22 views
5

En una clase Java, tengo un método que a veces lleva mucho tiempo para la ejecución. Tal vez se cuelga en ese flujo de método. Lo que quiero es que si el método no se completa en un tiempo específico, el programa debe salir de ese método y continuar con el resto del flujo.Método de tiempo de espera en java

Háganme saber si hay alguna forma de manejar esta situación.

Respuesta

7

Debe usar hilos para lograr esto. Los hilos no son dañinos :) El ejemplo a continuación ejecuta un fragmento de código durante 10 segundos y luego lo finaliza.

public class Test { 
    public static void main(String args[]) 
     throws InterruptedException { 

     Thread thread = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("0"); 
       method(); 
      } 
     }); 
     thread.start(); 
     long endTimeMillis = System.currentTimeMillis() + 10000; 
     while (thread.isAlive()) { 
      if (System.currentTimeMillis() > endTimeMillis) { 
       System.out.println("1"); 
       break; 
      } 
      try { 
       System.out.println("2"); 
       Thread.sleep(500); 
      } 
      catch (InterruptedException t) {} 
     } 


    } 

    static void method() { 
     long endTimeMillis = System.currentTimeMillis() + 10000; 
     while (true) { 
      // method logic 
      System.out.println("3"); 
      if (System.currentTimeMillis() > endTimeMillis) { 
       // do some clean-up 
       System.out.println("4"); 
       return; 
      } 
     } 
    } 
} 
+0

¡Genial! Trabajado perfeccionado para mí. – Haych

1

Ejecute el método en un subproceso diferente, puede finalizar un subproceso en cualquier momento.

+0

¿Hay alguna forma de no usar Threads? No quiero usar Threads. – Ran

+0

@Rana _No quiero usar Threads_ ¿Por qué? Si no está familiarizado, eche un vistazo al [tutorial de Java] (http://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html) – COD3BOY

+0

Hola Sanjay, el problema con los hilos es que estamos no estoy seguro acerca de la ejecución del flujo de subprocesos si tenemos varios subprocesos ejecutándose para la misma porción de código que parece ser un poco complejo de administrar o depurar. – Ran

0

Basado en el snipplet anterior, traté de crear un bean de primavera glorificado.

Tal ejecutor corre el pasado limitedRuntimeTask en limitados runtimeInMs. Si la tarea finaliza dentro de sus límites de tiempo, la persona que llama continúa normalmente en ejecución.

Si el limitedRuntimeTask no logra terminar en los runtimeInMs definidos, la persona que llama recibirá la ejecución del hilo de vuelta. Si se definió timeBreachedTask, se ejecutará antes de regresar a la persona que llama.

public class LimitedRuntimeExecutorImpl { 


public void runTaskInLessThanGivenMs(int runtimeInMs, final Callable limitedRuntimeTask, final Callable timeBreachedTask) { 
    Thread thread = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       LOGGER.info("Started limitedRuntimeTask"); 
       limitedRuntimeTask.call(); 
       LOGGER.info("Finished limitedRuntimeTask in time"); 
      } catch (Exception e) { 
       LOGGER.error("LimitedRuntimeTask exception", e); 
      } 
     } 
    }); 
    thread.start(); 

    long endTimeMillis = System.currentTimeMillis() + runtimeInMs; 

    while (thread.isAlive()) { 
     if (System.currentTimeMillis() > endTimeMillis) { 
      LOGGER.warn("LmitedRuntimeTask did not finish in time (" + runtimeInMs + ")ms. It will run in vain."); 
      if(timeBreachedTask != null){ 
       try { 
        LOGGER.info("Executing timeBreachedTask"); 
        timeBreachedTask.call(); 
        LOGGER.info("Finished timeBreachedTask"); 
       } catch (Exception e) { 
        LOGGER.error("timeBreachedTask exception", e); 
       } 
      } 
      return; 
     } 
     try { 
      Thread.sleep(10); 
     } 
     catch (InterruptedException t) {} 
    } 

} 

}

0

me siento el enfoque en respuesta aceptada es un poco anticuado. Con Java8, se puede hacer mucho más simple.

Diga, usted tiene un método

MyResult conjureResult(String param) throws MyException { ... } 

entonces usted puede hacer esto (seguir leyendo, esto es sólo para mostrar el enfoque):

private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor(); 

MyResult conjureResultWithTimeout(String param, int timeoutMs) throws Exception { 
    Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param)); 
    return future.get(timeoutMs, TimeUnit.MILLISECONDS); 
}  

por supuesto, lanzando excepción es malo, aquí está la versión extendida correcta con el procesamiento correcto de errores, pero le sugiero que la examine cuidadosamente; es posible que desee hacer algunas cosas de manera diferente (registro, tiempo de espera excedido en resultado extendido, etc.):

private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor(); 

MyResult conjureResultWithTimeout(String param, int timeoutMs) throws MyException { 
    Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param)); 
    try { 
     return future.get(timeoutMs, TimeUnit.MILLISECONDS); 
    } catch (InterruptedException e) { 
     //something interrupted, probably your service is shutting down 
     Thread.currentThread().interrupt(); 
     throw new RuntimeException(e); 
    } catch (ExecutionException e) { 
     //error happened while executing conjureResult() - handle it 
     if (e.getCause() instanceof MyException) { 
      throw (MyException)e.getCause(); 
     } else { 
      throw new RuntimeException(e); 
     } 
    } catch (TimeoutException e) { 
     //timeout expired, you may want to do something else here 
     throw new RuntimeException(e); 
    } 
} 
Cuestiones relacionadas