Java循环持续一段时间

时间:2010-03-31 04:41:19

标签: java time loops

有没有办法可以轻松地在一段时间内进行for循环? (不使用System.currentTimeMillis()测量时间?)

即。我想在Java中做这样的事情:

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

由于

8 个答案:

答案 0 :(得分:24)

不,没有内置的构造可以做到这一点。

我想指出,您不应该使用System.currentTimeMillis()在指定的时间段内执行或延迟任务。而是使用System.nanoTime()。前一种方法在Windows中不准确,而后一种方法无论操作系统如何都是准确的。您可以使用TimeUnit枚举轻松地在毫秒之间或任何其他时间单位之间,以纳秒为单位。

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

答案 1 :(得分:10)

我认为这就是你想要的:

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标志(更便宜)。

编辑

实际上没有安全替代轮询时钟或轮询标志。理论上,您可以修改上述片段以调用不推荐使用的 Thread.stop()方法,而不是Thread.interrupt()

(我建议使用Thread.stop()和朋友。它们存在缺陷,使用起来很危险。我只是将其视为理论替代品。)

编辑2

请注意,使用Thread.interrupt()优于设置共享标志:

  • Thread.interrupt()将导致某些阻塞I / O和同步方法解除阻塞并抛出已检查的异常。更新共享标志不会这样做。

  • 某些第三方库也会检查中断标志,看看它们是否应该停止正在进行的操作。

  • 如果你的循环涉及对其他方法的调用等,Thread.interrupt()意味着你不必担心这些方法可以访问标志......如果需要的话。

编辑3

只是要补充说sleep(N)不能保证在N毫秒之后唤醒睡眠线程。但在正常情况下,它会相当接近。

答案 2 :(得分:3)

我为这个问题做了一个简单但很糟糕的实现。我想避免使用Timer和TimeTask,最终得到了这个quickfix解决方案。

主要想法是我只是想创建一个独立的倒数计时器,我可以启动并调用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) {

    }
}
}

答案 3 :(得分:1)

没有。考虑到简单地编写一个使用System.currentTimeMillis()(或者您选择的任何时间函数)的函数,这是一个奇怪的请求。情况的更多背景可能是有序的。

答案 4 :(得分:1)

这是另一个建议:

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();
    }
}

}

该方法反复执行提供的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(); } } 的{​​{1}}方法,直到计时器到期为止。

注意事项:

  • 时间是近似的。
  • 请注意如何实施run()方法,因为它可能会占用您的所有CPU能力。
  • 除非您为要执行的每个Runnable创建run()类的新实例,否则实现不是线程安全的。

答案 5 :(得分:0)

我认为没有办法循环一段时间而不检查你是否已经循环了一段时间。

答案 6 :(得分:0)

根据您的使用情况,类Thread 中的两个sleep()方法中的任何一个可能符合条件,但听起来您必须对System.currentTimeMillis()大惊小怪,这看起来很奇怪。

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

答案 7 :(得分:0)

循环迭代值比较,而不是持续时间。因此,如果没有自己分配和比较系统时间,你就无法做到。 如果您希望它是直观的,那么您可以拥有一个内部使用毫秒的函数,但需要Minutes作为参数并使用它。

不,你不能在其中使用线程或睡眠方法,因为这不能确保准确的时间。如果您的处理器在给定时间过后忙于其他一些线程,那么您的线程将继续等待。