我想写一个java while循环,它会迭代15秒。我认为这样做的一种方法是存储当前系统时间+ 15秒,然后将其与while循环签名中的当前时间进行比较。
有更好的方法吗?
答案 0 :(得分:53)
这个设计取决于你想要做什么15s。两个最合理的案例是“每15秒执行一次此操作”或“等待X发生或15秒即将到来”,这将导致非常不同的代码。
这不会迭代,但是如果你想为15s做任何事情都会更有效率(它什么都不做会浪费更少的CPU)。
如果你真的想循环15秒,那么你的解决方案就可以了,只要你的代码不需要太长时间。类似的东西:
long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
// do something
// pause to avoid churning
Thread.sleep( xxx );
}
如果您希望代码在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页)。
答案 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);
}
}