2012-01-24 6 views
5

Dans une classe java, j'ai une méthode qui prend parfois beaucoup de temps pour l'exécution. Peut-être qu'il se bloque dans ce flux de méthode. Ce que je veux, c'est que si la méthode ne se termine pas à un moment précis, le programme devrait quitter cette méthode et continuer avec le reste du flux.Méthode time out dans java

S'il vous plaît laissez-moi savoir est-il un moyen de gérer cette situation.

Répondre

7

Pour ce faire, vous devez utiliser des unités d'exécution. Les threads ne sont pas dangereux :) Exemple ci-dessous exécuter un morceau de code pendant 10 secondes, puis le termine.

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

Super! Travaillé parfait pour moi. – Haych

1

Exécutez la méthode dans un thread différent, vous pouvez terminer un thread à tout moment.

+0

Existe-t-il un moyen sans utiliser Threads.Je ne veux pas utiliser Threads. – Ran

+0

@Rana _Je ne veux pas utiliser Threads_ Pourquoi? Si vous n'êtes pas familier, jetez un oeil au [tutoriel java] (http://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html) – COD3BOY

+0

Salut Sanjay, le problème avec les threads est que nous sommes pas sûr de l'exécution du flux de threads si nous avons plusieurs threads en cours d'exécution pour la même partie du code qui semble être un peu complexe à gérer ou à déboguer. – Ran

0

Basé sur le snipplet ci-dessus, j'ai essayé de créer un grain de printemps glorifié.

exécuteur testamentaire court le passé limitedRuntimeTask en limitées runtimeInMs. Si la tâche se termine dans les limites de temps, l'appelant poursuit normalement son exécution.

Si le limitedRuntimeTask ne parvient pas à terminer dans les définies runtimeInMs, l'appelant recevra l'exécution du thread en arrière. Si une timeBreachedTask a été définie, , elle sera exécutée avant de retourner à l'appelant.

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

Je me sens l'approche en réponse acceptée est un peu vieillot. Avec Java8, cela peut être fait beaucoup plus simple.

Dites, vous avez une méthode

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

alors vous pouvez le faire (continuez à lire, c'est juste pour montrer l'approche):

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); 
}  

bien sûr, jeter exception est mauvais, voici la version étendue correcte avec le traitement des erreurs correctes, mais je vous suggère de l'examiner attentivement, vous voudrez peut-être faire certaines choses différemment (enregistrement, retour du délai dans le résultat étendu, 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); 
    } 
}