在 Java 中运行代码 x 秒?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2029118/
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 02:46:39  来源:igfitidea点击:

Run code for x seconds in Java?

javatimewhile-loop

提问by Danny King

I'd like to write a java while loop that will iterate for 15 seconds. One way I thought to do this would be to store the current system time + 15sec and then compare that to the current time in the while loop signature.

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

Is there a better way?

有没有更好的办法?

采纳答案by Nick Fortescue

The design of this depends on what you want doing for 15s. The two most plausible cases are "do this every X for 15s" or "wait for X to happen or 15s whichever comes sooner", which will lead to very different code.

这的设计取决于你想在 15 秒内做什么。两个最合理的情况是“每 X 执行一次此操作 15 秒”或“等待 X 发生或等待 15 秒,以较早者为准”,这将导致非常不同的代码。

Just waiting

只是等待

Thread.sleep(15000)

线程睡眠(15000)

This doesn't iterate, but if you want to do nothing for 15s is much more efficient (it wastes less CPU on doing nothing).

这不会迭代,但如果你想在 15 秒内什么都不做,效率会更高(它在什么都不做时浪费更少的 CPU)。

Repeat some code for 15s

重复一些代码 15 秒

If you really want to loop for 15s then your solution is fine, as long as your code doesn't take too long. Something like:

如果您真的想循环 15 秒,那么您的解决方案很好,只要您的代码不会花费太长时间。就像是:

long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
  // do something
  // pause to avoid churning
  Thread.sleep( xxx );
}

Wait for 15s or some other condition

等待 15 秒或其他一些条件

If you want your code to be interrupted after exactly 15s whatever it is doing you'll need a multi-threaded solution. Look at java.util.concurrentfor lots of useful objects. Most methods which lock (like wait() ) have a timeout argument. A semaphoremight do exactly what you need.

如果您希望您的代码在 15 秒后被中断,无论它在做什么,您都需要一个多线程解决方案。查看java.util.concurrent以获取许多有用的对象。大多数锁定的方法(如 wait() )都有一个超时参数。一个信号可能做的正是你所需要的。

回答by Michel Gokan

try this:

尝试这个:

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

more info : here

更多信息:这里

回答by Tom Hawtin - tackline

Assuming you want the loop to do something sensible, you might find it faster to check a volatile flag. Have another thread wait 15 seconds (or use a timer) and then set it.

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

Alternatively, if you know roughly how long the loop body will take, run it a few hundred times, say, and do the time check in an outer loop.

或者,如果您大致知道循环体需要多长时间,那么运行几百次,然后在外循环中进行时间检查。

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

System.nanoTimeshouldnot get confused by system clock changes. Use of long literal numbers is important.

System.nanoTime不应被系统时钟更改所迷惑。使用长字面数字很重要。

回答by YuppieNetworking

You might be interested in scheduling a TimerTask that stops another thread or changes the condition of your loop.

您可能对调度停止另一个线程或更改循环条件的 TimerTask 感兴趣。

回答by Alexander Pogrebnyak

Never check for current time in a tight loop.

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

Otherwise somebody with a laptop can get get his/her lap burned by an overheated CPU. I heard the stories of this actually happening.

否则,使用笔记本电脑的人可能会因 CPU 过热而烧毁他/她的膝盖。我听说过这种真实发生的故事。

回答by Binil Thomas

As already mentioned by other posters, if you just want the thread to pause for some time use Thread.sleep().

正如其他海报已经提到的,如果您只想让线程暂停一段时间,请使用Thread.sleep().

If you want the thread to do something, but want to make it stop after a while, use something like:

如果你想让线程做一些事情,但想让它在一段时间后停止,使用类似的东西:

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 { /* .. */ }
}

and from the main thread, do:

并从主线程,执行:

Foo foo = new Foo(); 
Thread thread = new Thread(foo);
thread.start();

/* when you want to stop it */
foo.kill();
thread.interrupt();

回答by Robert Christie

Your general approach seems fine although you may want to see if the current time is greater than the point you want to stop, otherwise, you might be running for a long time.

尽管您可能想查看当前时间是否大于要停止的时间点,但您的一般方法似乎没问题,否则,您可能会运行很长时间。

The alternative is to run a timer/thread that sets a flag after 15 seconds have elapsed. This flag would have to be marked as volatile otherwise your loop might not see the change occur in the value.

另一种方法是运行一个计时器/线程,在 15 秒过去后设置一个标志。这个标志必须被标记为 volatile 否则你的循环可能看不到值发生了变化。

The choice if you care about efficiency is which is more expensive, getting the system time once per loop or accessing a volatile variable? I don't know which one is more efficient - you could benchmark it if it's really important.

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

For simple, maintainable code, I'd choose the timer check approach:

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

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

回答by Steven G. Brown

For the java.util.concurrentapproach, refer to Chapter 6 of Java Concurrency in Practice(section 6.3.7 Placing time limits on tasks, page 131).

有关java.util.concurrent方法,请参阅Java 并发实践中的第 6 章(第 6.3.7 节为任务设置时间限制,第 131 页)。

Code example: Fetching an advertisement with a time budget.

代码示例:获取带有时间预算的广告。

回答by Peter Lawrey

A solution similar to @Tom Hawtin without an arbitary loop size.

类似于@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);

In this case the size of the inner loop will start small but grow in size if the loop is particularly quick. If it is slow enough, it might only iterate once.

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

回答by yegor256

You can use AOP and a @Timeableannotation from jcabi-aspects(I'm a developer):

您可以使用 AOP 和@Timeable来自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
}

When time limit is reached your thread will get interrupted()flag set to trueand it's your job to handle this situation correctly and to stop execution.

当达到时间限制时,您的线程将被interrupted()设置为标志,true您的工作是正确处理这种情况并停止执行。