Цикл Java на определенное время

Существует ли способ, которым я могу сделать для цикла для определенного количества времени легко? (не измеряя время самостоятельно с помощью System.currentTimeMillis ()?)

Т.е. Я хочу сделать что-то вроде этого в Java:

int x = 0;
for( 2 minutes )  {
   System.out.println(x++);
}

Спасибо

11
задан Don Ch 31 March 2010 в 04:41
поделиться

7 ответов

Нет, встроенной конструкции, которая бы это делала, не существует.

Хочу заметить, что не следует использовать System.currentTimeMillis() для выполнения или отсрочки задачи на определенный период времени. Вместо этого используйте System.nanoTime(). Первый метод неточен в Windows, в то время как второй метод точен независимо от ОС. Вы можете использовать перечисление TimeUnit, чтобы легко перейти от времени в миллисекундах или любой другой единице времени к времени в наносекундах.

for (long stop=System.nanoTime()+TimeUnit.SECONDS.toNanos(2);stop>System.nanoTime();) {
  /*
   * Hammer the JVM with junk
   */
}
24
ответ дан 3 December 2019 в 01:33
поделиться

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

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

0
ответ дан 3 December 2019 в 01:33
поделиться

Вот еще одно предложение:

 открытый класс TimerLoop {
закрытый конечный цикл AtomicBoolean = новый AtomicBoolean (); 

public void run(Runnable runnable, long duration, TimeUnit timeUnit) {
    loop.set(true);
    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            loop.set(false);
        }
    };
    Timer timer = new Timer();
    timer.schedule(task, timeUnit.toMillis(duration));
    while (loop.get()) {
        runnable.run();
    }
}

}

Метод повторно выполняет метод run () предоставленного Runnable , пока не истечет время таймера.

Соображения:

  • Время будет приблизительным.
  • Будьте осторожны при реализации метода run () , поскольку он потенциально потребляет всю мощность вашего процессора.
  • Реализация не является поточно-ориентированной, если вы не создадите новый экземпляр класса TimerLoop для каждого Runnable , который вы хотите выполнить.
1
ответ дан 3 December 2019 в 01:33
поделиться

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

Thread thread = Thread.currentThread();
thread.sleep(10);      // 10 milliseconds
thread.sleep(12, 345); // 12 milliseconds and 345 nanoseconds.
0
ответ дан 3 December 2019 в 01:33
поделиться

Я думаю, что это то, что вам нужно:

private final Thread thisThread = Thread.current();
private final int timeToRun = 120000; // 2 minutes;

new Thread(new Runnable() {
    public void run() {
        sleep(timeToRun);
        thisThread.interrupt();
    }
}).start();

while (!Thread.interrupted()) {
    // do something interesting.
}

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

РЕДАКТИРОВАТЬ

На самом деле нет безопасной альтернативы опросу часов или опросу флага. Теоретически вы можете изменить приведенный выше фрагмент, чтобы вызвать устаревший метод Thread.stop () вместо Thread.interrupt () .

НЕ рекомендую использовать Thread.stop () и друзей. Они ошибочны и опасны в использовании. Я просто представляю это как теоретический альтернатива.)

РЕДАКТИРОВАТЬ 2

Просто чтобы указать, что использование Thread.interrupt () имеет преимущества перед установкой общего флага:

  • Thread.interrupt () вызовет определенные методы блокировки ввода-вывода и синхронизации для разблокировки и выдачи проверенного исключения. Обновление общего флага этого не сделает.

  • Некоторые сторонние библиотеки также проверяют флаг прерывания, чтобы узнать, следует ли им останавливать то, что они в настоящее время делают.

  • Если ваш цикл включает вызовы других методов и т. Д., Thread.interrupt () означает, что вам не нужно беспокоиться о том, что эти методы могут получить доступ к флагу ... при необходимости.

РЕДАКТИРОВАТЬ 3

Просто добавлю, что sleep (N) не гарантированно разбудит спящий поток ровно через N миллисекунд. Но при нормальных обстоятельствах это будет достаточно близко.

10
ответ дан 3 December 2019 в 01:33
поделиться

Я не думаю, что есть способ зацикливаться в течение определенного периода времени, не проверяя, зацикливались ли вы в течение определенного периода времени.

0
ответ дан 3 December 2019 в 01:33
поделиться

Нет. Это своего рода странный запрос, учитывая, насколько просто было бы просто написать функцию, использующую System.currentTimeMillis () (или любую другую функцию времени, которую вы выберете). Возможно, будет уместно более подробный контекст ситуации.

1
ответ дан 3 December 2019 в 01:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: