Подтвердить что ты не робот

Выполнить код на x секунд в Java?

Я бы хотел написать цикл java while, который будет повторяться в течение 15 секунд. Один из способов, который я решил сделать, - сохранить текущее системное время + 15 секунд, а затем сравнить его с текущим временем в сигнатуре цикла while.

Есть ли лучший способ?

4b9b3361

Ответ 1

Дизайн этого зависит от того, что вы хотите делать за 15 секунд. Два наиболее правдоподобных случая: "сделайте это каждый X за 15 секунд" или "подождите, пока произойдет X" или 15 секунд в зависимости от того, что наступит раньше ", что приведет к очень разному коду.

Ожидание

Thread.sleep(15000)

Это не итерация, но если вы ничего не хотите делать за 15 секунд, это намного эффективнее (он тратит меньше процессор на то, чтобы ничего не делать).

Повторите код за 15 секунд

Если вы действительно хотите зацикливаться на 15 секунд, тогда ваше решение будет прекрасным, если ваш код не займет слишком много времени. Что-то вроде:

long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
  // do something
  // pause to avoid churning
  Thread.sleep( xxx );
}

Подождите 15 секунд или какое-либо другое условие

Если вы хотите, чтобы ваш код был прерван после ровно 15 секунд, что бы он ни делал, вам понадобится многопоточное решение. Посмотрите java.util.concurrent для множества полезных объектов. Большинство методов, которые блокируют (например, wait()), имеют аргумент тайм-аута. A semaphore может делать именно то, что вам нужно.

Ответ 2

попробуйте следующее:

public class SleepMessages {
    public static void main(String args[]) throws InterruptedException {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };

        for (int i = 0; i < importantInfo.length; i++) {
            //Pause for 15 seconds
            Thread.sleep(15000);
            //Print a message
            System.out.println(importantInfo[i]);
        }
    }
}

Дополнительная информация: здесь

Ответ 3

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

Если вы хотите, чтобы нить что-то делал, но хотите сделать это через некоторое время, используйте что-то вроде:

class Foo implements Runnable {
    private volatile boolean killed = false;

    public void run() {
        while (!killed) {
            try { doOnce(); } catch (InterruptedException ex) { killed = true; }
        }
    }

    public void kill() { killed = true; }
    private void doOnce() throws InterruptedException { /* .. */ }
}

и из основного потока выполните:

Foo foo = new Foo(); 
Thread thread = new Thread(foo);
thread.start();

/* when you want to stop it */
foo.kill();
thread.interrupt();

Ответ 4

Ваш общий подход кажется прекрасным, хотя вы можете посмотреть, больше ли текущее время, чем точка, которую вы хотите остановить, в противном случае вы можете работать в течение длительного времени.

Альтернативой является запуск таймера/потока, который устанавливает флаг через 15 секунд. Этот флаг должен быть отмечен как изменчивый, иначе ваш цикл может не увидеть изменения в значении.

Выбор, если вы заботитесь об эффективности, является более дорогостоящим, получая системное время один раз за цикл или доступ к изменчивой переменной? Я не знаю, какой из них более эффективен - вы можете сравнить его, если это действительно важно.

Для простого, поддерживаемого кода, я бы выбрал подход проверки таймера:

long endTime = System.currentTimeMillis() + 15000
while (System.currentTimeMillis() < endTime) {
  //loop
} 

Ответ 5

Предполагая, что вы хотите, чтобы цикл делал что-то разумное, вы можете быстрее найти флажок волатильности. Попросите еще один поток подождать 15 секунд (или используйте таймер), а затем установите его.

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

final long start = System.nanoTime();
do {
    for (int i=0; i<200, ++i) {
        ...
    }
} while (System.nanoTime()-start < 15L*1000L*1000L*1000L);

System.nanoTime не следует путать изменения системных часов. Использование длинных буквенных чисел важно.

Ответ 6

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

Ответ 7

Никогда не проверяйте текущее время в замкнутом контуре.

В противном случае кто-то с ноутбуком может получить, чтобы его/ее колпак загорелся перегретым процессором. Я слышал рассказы об этом на самом деле.

Ответ 9

Решение, подобное @Tom Hawtin, без сурового размера петли.

final long end = System.nanoTime() + 15 * 1000 * 1000 * 1000L;
int loop = 1;
do {
    for (int i=0; i<loop; ++i) {
        ...
    }
    loop++;
} while (System.nanoTime() < end);

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

Ответ 10

Вы можете использовать AOP и @Timeable аннотация из jcabi-aspects (я разработчик):

@Timeable(limit = 1, unit = TimeUnit.SECONDS)
String load(String resource) {
  // do this check regularly:
  if (Thread.currentThread.isInterrupted()) {
    throw new IllegalStateException("time out");
  }
  // execution as normal
}

Когда достигнут лимит времени, ваш поток получит флаг interrupted(), установленный на true, и ваше задание правильно обрабатывает эту ситуацию и прекратит выполнение.

Ответ 11

Вот мое предложение, и это работает хорошо для меня:)

StoppingTime = 15 ;
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000 ;
for (int i=0; i<loop; ++i) {
    // your code here

    loop++;
    if (((System.currentTimeMillis()/1000) - StartTime) > StoppingTime)
        loop=0;
}

Ответ 12

Я предлагаю вам сделать это с помощью класса таймера, избегая Thread.sleep(xxx); Метод.

например:

import java.util.Timer;
import java.util.TimerTask;

public class TimerExample {
    private int globalTimer = 0;
    private int limitTimer = 15;

    public static void main(String[] args) {
        new TimerExample();
    }

    public TimerExample() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                globalTimer++;
                // DO YOUR CODE HERE
                System.out.println("running");
                if (globalTimer == limitTimer) {
                    timer.cancel();
                }
            }
        }, 0, 1000);
    }
}