在Java中运行x秒的代码?

时间:2010-01-08 16:46:31

标签: java time while-loop

我想写一个java while循环,它会迭代15秒。我认为这样做的一种方法是存储当前系统时间+ 15秒,然后将其与while循环签名中的当前时间进行比较。

有更好的方法吗?

12 个答案:

答案 0 :(得分:53)

这个设计取决于你想要做什么15s。两个最合理的案例是“每15秒执行一次此操作”或“等待X发生或15秒即将到来”,这将导致非常不同的代码。

等待

Thread.sleep(15000)

这不会迭代,但是如果你想为15s做任何事情都会更有效率(它什么都不做会浪费更少的CPU)。

重复一些代码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())都有一个超时参数。 semaphore可能完全符合您的需求。

答案 1 :(得分:4)

正如其他海报已经提到的,如果您只是希望线程暂停一段时间,请使用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();

答案 2 :(得分:3)

试试这个:

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

更多信息:here

答案 3 :(得分:2)

你的一般方法看起来很好,尽管你可能想看看当前时间是否大于你想要停止的点,否则你可能会运行很长时间。

另一种方法是运行一个定时器/线程,在15秒后设置一个标志。此标志必须标记为volatile,否则您的循环可能看不到值中发生的更改。

如果你关心效率的选择哪个更贵,每个循环获得一次系统时间或访问一个volatile变量?我不知道哪一个更有效率 - 如果真的很重要,你可以对它进行基准测试。

对于简单,可维护的代码,我会选择定时器检查方法:

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

答案 4 :(得分:1)

您可以使用来自@Timeable的AOP和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,你的工作就是正确处理这种情况并停止执行。

答案 5 :(得分:1)

这是我的建议,它对我有用:)

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

答案 6 :(得分:0)

假设您希望循环做一些合理的事情,您可能会发现检查易失性标记会更快。让另一个线程等待15秒(或使用计时器),然后设置它。

或者,如果您大致知道循环体将花费多长时间,比如运行它几百次,并在外循环中进行检查。

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

System.nanoTime 应该不会因系统时钟变化而感到困惑。使用长字面数字很重要。

答案 7 :(得分:0)

您可能有兴趣安排一个TimerTask停止另一个线程或更改循环条件。

答案 8 :(得分:0)

永远不要在紧密循环中检查当前时间。

否则,有笔记本电脑的人可能会因过热的CPU而烧伤他/她的膝盖。我听说过这个故事真的发生了。

答案 9 :(得分:0)

对于java.util.concurrent方法,请参阅Chapter 6 of Java Concurrency in Practice(第6.3.7节“对任务设置时间限制”,第131页)。

代码示例:Fetching an advertisement with a time budget.

答案 10 :(得分:0)

类似于没有仲裁循环大小的@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);

在这种情况下,内环的大小将从小开始,但如果循环特别快,则增大。如果它足够慢,它可能只迭代一次。

答案 11 :(得分:0)

我建议你用定时器类来避免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);
    }
}