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

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

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

person s2000coder    schedule 23.11.2010    source источник
comment
Кажется, мы здесь перефразируем старую ветку: stackoverflow.com/questions/2550536/   -  person Dmitri    schedule 23.11.2010
comment
Возможный дубликат Как отключить поток   -  person vhunsicker    schedule 25.11.2016


Ответы (4)


вам следует попробовать новые службы 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();
        }
    }
}
person d0x    schedule 30.03.2012
comment
какое значение тайм-аута было установлено здесь? - person nikk; 09.07.2016
comment
Что вы имеете в виду под таймаутом? Thread.sleep(1337);? - person Murmel; 07.09.2016
comment
Я считаю, что под таймаутом @nikk означает время, по истечении которого служба будет отключена. - person lostsoul29; 08.06.2017
comment
@nikk Тайм-аут составляет 1 секунду. Посмотрите: f.get () - person Sebastian D'Agostino; 10.08.2017
comment
Это не останавливает программу. Моя программа длится 20 секунд. Он показывает, что вычисление заняло много времени после 1 секунды, но не останавливает программу. Я все еще вижу результат через 20 секунд. - person Rohit Singh; 02.09.2020

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

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, который вы настроили, позаботится о прерывании потока. Это позволит вам получить более точное разрешение без циклического опроса.

person MBCook    schedule 23.11.2010
comment
Однако .interrupt() работает не так. Если поток не заблокирован, он просто устанавливает флаг interrupted, поток все равно должен проверить его, чтобы остановить выполнение. Кроме того, InterruptedException - это проверенное исключение, вы не можете просто выбросить его вокруг произвольного кода (ваш пример не будет компилироваться). - person Dmitri; 23.11.2010

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

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

person Dmitri    schedule 23.11.2010

person    schedule
comment
но если одна итерация цикла начинается с 59 секунд, и каждая итерация цикла занимает более 1 секунды, вы бы прошли более 60 секунд, верно? Это лучшее, что можно сделать. Я спрашиваю по чистому незнанию. - person Ramy; 23.11.2010
comment
@ Рэми: нет. start и end - абсолютные времена, измеряемые в миллисекундах с начала эпохи (полночь, 1 января 1970 г. по всемирному координированному времени). Ролловера нет. - person Matt Ball; 23.11.2010
comment
хорошо, но проверка происходит только в начале цикла. Итак, если в начале цикла, скажем, прошло 59 секунд, а каждая итерация цикла занимает, скажем, 5 секунд. В следующий раз, когда будет проверяться условие цикла while, пройдут 64 секунды. Верно, или я что-то упускаю? - person Ramy; 23.11.2010
comment
@ Рэми: ты все еще скучаешь по нему. Цикл начинается с нуля миллисекунд (для всех намерений и целей). Подумайте об этом так, как это установила математика: прежде чем я войду в цикл, я получаю текущее время. Чтобы выяснить, когда цикл должен закончиться, я добавляю к текущему времени 60 секунд (60 000 мс). Условие цикла ложно через 60 секунд. - person Matt Ball; 23.11.2010
comment
Я считаю, что Рами прав. Предположим, что работа в цикле занимает 7 секунд. После одного запуска у вас будет 7 секунд, затем 14 ... пока вы не завершите 8 итераций, в общей сложности 56 секунд. Проверка будет успешной (поскольку вам меньше 60 лет), но тогда вычисления займут 7 секунд. К тому времени, когда проверка будет сделана снова, у вас будет 63 секунды. Это 5% с течением времени. - person MBCook; 23.11.2010
comment
Хорошо, я с тобой. Но что, если мы дойдем до шестидесяти секунд ВНУТРИ ПЕТЛИ? Возможно, это лучший способ сделать это, но MBCook понимает мою точку зрения. - person Ramy; 23.11.2010
comment
Это подходящее решение, в моей программе нет жесткого ограничения. Спасибо вам, ребята! - person s2000coder; 23.11.2010
comment
@MBCook: Я не понимаю твоей точки зрения. Какое решение лучше? Прервать вычисление в середине цикла? Сомнительно. - person Matt Ball; 23.11.2010
comment
Я склонен согласиться с Рами. Ваше предложение работает только до тех пор, пока код в цикле не длится дольше, чем end-start. Если бит с именем // run длится 61 секунду - ›сбой. - person Andrew Magerman; 23.05.2014
comment
@MattBall Почему сомнительно прерывать вычисление? Это действительно зависит от ваших потребностей. Вероятно, вы получили несколько голосов против, потому что не объяснили, на что на самом деле направлен ваш код - ›предотвращение выполнения кода выполнения снова через 60 секунд. Это сильно отличается от завершения через 60 секунд, что люди, читающие вопрос, вероятно, ожидали бы сделать. - person Murmel; 07.09.2016