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

Цикл Java на определенную продолжительность

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

т.е. Я хочу сделать что-то подобное в Java:

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

Спасибо

4b9b3361

Ответ 1

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

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

for (long stop=System.nanoTime()+TimeUnit.SECONDS.toNanos(2);stop>System.nanoTime();) {
  /*
   * Hammer the JVM with junk
   */
}

Ответ 2

Я думаю, что это то, что вы хотите:

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.
}

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

EDIT

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

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

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

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

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

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

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

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

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

Ответ 3

Я сделал простую, но sucky, реализацию для этой проблемы. Я хотел избежать Timer и TimeTask и в итоге решил это быстро решить.

Основная идея заключается в том, что я просто хотел создать независимый таймер обратного отсчета, который я мог бы просто запустить, и вызвать isFinished(), чтобы проверить, завершен ли обратный отсчет.

package RIPv3;

/**
 * Creates a countdown timer which runs its own thread and uses CountdownTimerThread,                which runs yet another
 * thread.
 *
 * start() method is called to start the countdown.
 * isFinished() method is called to check if the countdown is finished or not.
 * 
 * ! Be Aware!
 * This is a quickfix and sucky implementation.
 * There will be a small delay. This is not accurate.
 * 
 * @author Endre Vestbø
 * @version 1.0 (09.05.2011)
 */
public class CountdownTimer extends Thread {
/* Countdown timer */
private CountdownTimerThread timer;

/**
 * Creates a new timer and sets time to count down
 * @param time
 *          Time to count down
 */
public CountdownTimer(long time) {
    this.timer = new CountdownTimerThread(time);
}

public void run() {
    this.timer.start();
}

/**
 * @return
 *      False if timer is running, else true
 */
public boolean isFinished() {
    if(this.timer.getState() == Thread.State.TERMINATED)
        return true;

    return false;
}   
}

 package RIPv3;

/**
 * Used by CountdownTimer to count down time.
 * 
 * @author Endre Vestbø
 * @version 1.0  (09.05.2011)
 *
 */
public class CountdownTimerThread extends Thread {
private long time;

/** Create a new timer */
public CountdownTimerThread(long time) {
    this.time = time;
}

/**
 * Start a countdown
 * @param period
 *      Period to count down given in milliseconds
 */
public void run() {
    try {
        sleep(this.time);
    } catch (InterruptedException e) {

    }
}
}

Ответ 4

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

Ответ 5

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


public class TimerLoop {
    private final AtomicBoolean loop = new 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, который вы хотите выполнить.

Ответ 6

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

Ответ 7

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

Thread thread = Thread.currentThread();
thread.sleep(10);      // 10 milliseconds
thread.sleep(12, 345); // 12 milliseconds and 345 nanoseconds.

Ответ 8

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

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