Как остановить выполнение после определенного времени в Java?

В коде переменная timer будет указывать продолжительность, после которой завершается цикл while, например 60 секунд.

   while(timer) {
    //run
    //terminate after 60 sec
   }

4 ответа

Решение
long start = System.currentTimeMillis();
long end = start + 60*1000; // 60 seconds * 1000 ms/sec
while (System.currentTimeMillis() < end)
{
    // run
}

Вы должны попробовать новые Java Executor Services. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

При этом вам не нужно программировать цикл измерения времени самостоятельно.

public class Starter {

    public static void main(final String[] args) {
        final ExecutorService service = Executors.newSingleThreadExecutor();

        try {
            final Future<Object> f = service.submit(() -> {
                // Do you long running calculation here
                Thread.sleep(1337); // Simulate some delay
                return "42";
            });

            System.out.println(f.get(1, TimeUnit.SECONDS));
        } catch (final TimeoutException e) {
            System.err.println("Calculation took to long");
        } catch (final Exception e) {
            throw new RuntimeException(e);
        } finally {
            service.shutdown();
        }
    }
}

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

Thread t = new Thread(myRunnable); // myRunnable does your calculations

long startTime = System.currentTimeMillis();
long endTime = startTime + 60000L;

t.start(); // Kick off calculations

while (System.currentTimeMillis() < endTime) {
    // Still within time theshold, wait a little longer
    try {
         Thread.sleep(500L);  // Sleep 1/2 second
    } catch (InterruptedException e) {
         // Someone woke us up during sleep, that's OK
    }
}

t.interrupt();  // Tell the thread to stop
t.join();       // Wait for the thread to cleanup and finish

Это даст вам разрешение примерно до 1/2 секунды. Опрашивая чаще в цикле while, вы можете получить это.

Запуск вашего runnable будет выглядеть примерно так:

public void run() {
    while (true) {
        try {
            // Long running work
            calculateMassOfUniverse();
        } catch (InterruptedException e) {
            // We were signaled, clean things up
            cleanupStuff();
            break;           // Leave the loop, thread will exit
    }
}

Обновление на основе ответа Дмитрия

Дмитрий указал на TimerTask, который позволит вам избежать цикла. Вы можете просто выполнить вызов объединения, и настроенная вами TimerTask позаботится о прерывании потока. Это позволит вам получить более точное разрешение без необходимости опроса в цикле.

Зависит от того, что делает цикл while. Если есть вероятность, что он будет блокироваться в течение длительного времени, используйте TimerTask запланировать задачу, чтобы установить stopExecution флаг, а также .interrupt() твоя нить.

Имея только временное условие в цикле, оно может находиться там вечно в ожидании ввода или блокировки (опять же, это может не быть проблемой для вас).

Другие вопросы по тегам