Java 循环一段时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2550536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:10:17  来源:igfitidea点击:

Java loop for a certain duration

javatimeloops

提问by Don Ch

Is there a way I can do a for loop for a certain amount of time easily? (without measuring the time ourselves using System.currentTimeMillis() ?)

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

I.e. I want to do something like this in Java:

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

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

Thanks

谢谢

采纳答案by Tim Bender

No, there isn't a built-in construct which does that.

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

I want to point out that you should not use System.currentTimeMillis() for performing, or delaying, a task for a specified time period. Instead use System.nanoTime(). The former method is inaccurate in Windows, while the latter method is accurate regardless of OS. You can use TimeUnit enum to easily go between time in milliseconds, or any other time unit, to time in nanoseconds.

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

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

回答by Joe Phillips

No. That is sort of a strange request considering how simple it would be to simply write a function that uses System.currentTimeMillis() (or whichever time function you choose). More context of the situation might be in order.

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

回答by Joe Phillips

I don't think there is a way to loop for a certain period of time without checking to see if you've looped for a certain period of time.

我不认为有一种方法可以循环一段时间而不检查你是否已经循环了一段时间。

回答by Jim Ferrans

Depending on your use case either of the two sleep() methods in class Threadmightfit the bill, but it sounds like you have to fuss with System.currentTimeMillis(), which seems strange.

根据您的用例,Thread类中的两个 sleep() 方法中的任何一个都可能符合要求,但听起来您必须对 System.currentTimeMillis() 大惊小怪,这似乎很奇怪。

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

回答by Vaishak Suresh

Loops iterate over value comparison and not for duration. So without yourself assigning and comparing the system time, you cannot do it. If however you wish it be intuitive, then you can have a function that internally uses milliseconds, but takes Minutes as argument and use it.

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

And No, you cannot use threads or the sleep method in it, because that does not ensure the exact time. If your processor is busy with some other thread after the given time elapses, then your thread will continue to wait.

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

回答by Stephen C

I think that this is what you want:

我认为这就是你想要的:

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

This avoids doing repeated syscalls to get the system clock value (which can be rather expensive) and polls the current thread's interruptedflag instead (much cheaper).

这避免了重复执行系统调用来获取系统时钟值(这可能相当昂贵)并interrupted改为轮询当前线程的标志(便宜得多)。

EDIT

编辑

There is actually no safealternative to polling the clock or polling a flag. In theory, you could modify the above fragment to call the deprecatedThread.stop()method instead of Thread.interrupt().

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

(I do NOTrecommend using Thread.stop()and friends. They are flawed, and dangerous to use. I'm just posing this as a theoreticalalternative.)

(我建议使用Thread.stop()和朋友们。它们有缺陷,使用起来很危险。我只是把它当作一种理论上的选择。)

EDIT 2

编辑 2

Just to point out that using Thread.interrupt()has the advantages over setting a shared flag:

只是要指出 usingThread.interrupt()比设置共享标志有优势:

  • Thread.interrupt() will cause certain blocking I/O and synchronization methods to unblock and throw a checked exception. Updating a shared flag won't do this.

  • Some third-party libraries also check the interrupt flag to see if they should stop what they are currently doing.

  • If your loop involves calls to other methods, etc, Thread.interrupt() means that you don't need to worry about those methods can access the flag ... if they need to.

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

  • 一些第三方库还会检查中断标志以查看它们是否应该停止当前正在执行的操作。

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

EDIT 3

编辑 3

Just to add that sleep(N)is not guaranteed to wake the sleeping thread up after exactly Nmilliseconds. But under normal circumstances, it will be reasonably close.

只是补充一点,sleep(N)并不能保证在N几毫秒后唤醒睡眠线程。但在正常情况下,它会合理地接近。

回答by matsev

Here is another suggestion:

这是另一个建议:

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

}

The method executes the run()method of the provided Runnablerepeatedly until the timer expires.

该方法重复执行所run()提供的方法,Runnable直到定时器超时。

Considerations:

注意事项:

  • The time will be approximate.
  • Be careful how you implement the run()method as it will potentially consume all your CPU power.
  • The implementation is not thread-safe unless you create a new instance of the TimerLoopclass for each Runnablethat you would like to execute.
  • 时间将是近似的。
  • 请注意您如何实现该run()方法,因为它可能会消耗您所有的 CPU 能力。
  • 该实现不是线程安全的,除非您TimerLoop为每个Runnable要执行的类创建一个新实例。

回答by Endre Vestb?

I made a simple, but sucky, implementation for this problem. I wanted to avoid Timer and TimeTask and ended up with this quickfix solution.

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

The main idea is that I simply wanted to create an independed countdown timer which I could just start and call isFinished() to check if the countdown is finished.

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

    }
}
}