2013-12-10 4 views
9

У меня есть метод, который записывается в базу данных. Требование состоит в том, чтобы убедиться, что этот метод не выполняется по истечении определенного времени. Если он вернется до этого, то ничего не должно быть сделано.Установка максимального времени выполнения для метода/потока

Один базовый подход, который я могу придумать, - это что-то вроде этого.

public class LimitedRuntime { 

    public static void writeToDb(){ 
      // writes to the database 
    } 

    public static void main(String[] args) { 
     long totalExecutionTime = 8000L; 
     long startTime = System.currentTimeMillis(); 

     while(System.currentTimeMillis() - startTime < totalExecutionTime) 
     { 
      writeToDb(); 
     } 
    } 
} 

Одна из проблем этого подхода заключается в том, что даже если метод возвращает до максимального общего времени выполнения, даже тогда программа останавливается так, чтобы ждать в течение времени, чтобы истечь.

Как я могу сделать это лучше (или, может быть, более правильно)? И если мы используем Thread, как мы можем узнать, какой Thread выполняет этот метод?

+0

Что касается самого невообразимого решения, 'Δt = t2 - t2' oO – Paranaix

ответ

15

Вы можете сделать это, отправив свою работу в качестве исполнителя:

public static void main(String[] args) { 
    ExecutorService executor = Executors.newFixedThreadPool(4); 

    Future<?> future = executor.submit(new Runnable() { 
     @Override 
     public void run() { 
      writeToDb();   //  <-- your job 
     } 
    }); 

    executor.shutdown();   //  <-- reject all further submissions 

    try { 
     future.get(8, TimeUnit.SECONDS); //  <-- wait 8 seconds to finish 
    } catch (InterruptedException e) { //  <-- possible error cases 
     System.out.println("job was interrupted"); 
    } catch (ExecutionException e) { 
     System.out.println("caught exception: " + e.getCause()); 
    } catch (TimeoutException e) { 
     future.cancel(true);    //  <-- interrupt the job 
     System.out.println("timeout"); 
    } 

    // wait all unfinished tasks for 2 sec 
    if(!executor.awaitTermination(2, TimeUnit.SECONDS)){ 
     // force them to quit by interrupting 
     executor.shutdownNow(); 
    } 
} 
+0

При прерывании Thread вы должны помнить, что вы необходимо добавить условие типа 'if (isInterrupted()) {return; } '. Без этого нить не будет прервана вообще! Не знаю, как это будет работать с интерфейсом Runnable ... – bobbel

+0

Да, я предположил, что драйвер DB должен поддерживать это. –

+0

Я не знаком с 'ExecutorService'. Я прочитаю об этом. Кстати, вы можете просто сказать мне a) Что происходит выше, если метод завершается и возвращается до истечения максимального времени? b) Я хочу немедленно прекратить метод, как только превысит лимит времени. Для этого следует использовать 'executor.awaitTermination (0, TimeUnit.SECONDS)'? – OneMoreError

3

Существует также решение AspectJ для этого с jcabi-aspects библиотеки:

@Timeable(limit = 5, unit = TimeUnit.SECONDS) 
public String writeToDb() { 
    // writeToDb 
} 

Существует статья объяснить его дальше: Limit Java Method Execution Time

Смежные вопросы