无论循环的大小如何,如何最多持续60秒运行For循环并完成所有迭代

问题描述 投票:-1回答:5
for(i=1;i<list.size();i++){
   //do something
   //For Eg: move marker to a new position on the map
} 

我希望以上循环完成所有迭代,而与列表的大小无关,并且还希望整个任务运行1分钟。 (60秒)

java for-loop delay
5个回答
1
投票

我真的不知道这是否是您想要的,但希望对您有所帮助。

import java.util.concurrent.TimeUnit;

for(i=1;i<list.size();i++){
  try {
          TimeUnit.SECONDS.sleep(1);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  // Execute thing you want to be executed every second
} 

作为说明:您遍历for循环,并且线程等待一秒钟,然后在TimeUnit.SECONDS.sleep(1);之后执行代码。如果列表的大小为60,则结束循环将需要一分钟。

编辑:在我看来,围绕睡眠功能进行尝试捕获可能更聪明。


1
投票

例如,您可以使用System.nanoTime()来测量循环的持续时间,然后使用TimeUnit.NANOSECONDS.sleep(...)使其等待其余时间,如下所示:

long start = System.nanoTime();
long desiredDuration = 60 * 1000 * 1000;

// your loop goes here

long duration = System.nanoTime() - start;
if (duration < desiredDuration)
    TimeUnit.NANOSECONDS.sleep(desiredDuration - duration);

0
投票

签出this

long start = System.currentTimeMillis();
long end = start + 60*1000; // 60 seconds * 1000 ms/sec

int i = 0;
while (System.currentTimeMillis() < end)
{
   // do something, check if i less than size of list
   i++;
}

不要忘记检查列表的大小。


0
投票

最佳解决方案是先计算所需的时间,然后在该范围内运行循环。

long finish=System.currentTimeMillis() + 60000;
while(System.currentTimeMillis() != finish)
   {
    //statements;
    //statements;
   }

如果您这次尝试配备CPU并使它保持空闲,则该过程称为busy waiting,但在许多情况下认为不方便,因此我建议为此目的使用Thread.sleep(duration)

希望收到您身边的进一步询问。


0
投票

要在一分钟内均匀分布N调用量,您必须将两次调用之间的延迟设置为60/(N-1)值。 -1是可选的,但会使第一次和最后一次调用恰好相隔60秒。 (就像带有N个梯级的梯子有N-1个空格一样)

当然,将sleep()与上述计算得出的数字一起使用,不仅会产生舍入误差,而且还会产生漂移,因为您会在延迟之间进行填充,并且填充也会花费时间。

更精确的解决方案是从当前时间中减去每次调用应发生的时间(由startTime + 60*i/(N-1)定义)。重新排列并重新公式化这些公式,您可以从已经过去的时间中减去“下一次调用应该经历的时间”。

当然,“经过时间”应该使用System.nanoTime()而不是System.currentTimeMillis()来计算,因为当时钟改变或计算机从待机状态恢复时,后者可能会跳转。

在此示例中,我将60秒更改为6秒,因此您可以更轻松地查看运行时的情况。

public static void main(String... args) throws Exception {
    int duration = 6; // seconds
    List<Double> list = IntStream.range(0, 10).mapToDouble(i->ThreadLocalRandom.current().nextDouble()).boxed().collect(Collectors.toList());

    long startTime = System.nanoTime();
    long elapsed   = 0;
    for (int i = 0; i < list.size(); i++) { // Bug fixed: start at 0, not at 1.
        if (i > 0) {
            long nextInvocation = TimeUnit.NANOSECONDS.convert(duration, TimeUnit.SECONDS) * i / (list.size() - 1);
            long sleepAmount    = nextInvocation - elapsed;
            TimeUnit.NANOSECONDS.sleep(sleepAmount);
        }

        elapsed = System.nanoTime() - startTime;
        doSomething(elapsed, list.get(i));
    }
}

private static void doSomething(long elapsedNanos, Double d) {
    System.out.println(elapsedNanos / 1.0e9f + "\t" + d);
}

当然,当您为每个列表元素执行的任务所花费的时间超过60/(N-1)秒时,您就会出现争用,并且总是会超过“经过的时间”期限。使用此算法,总时间仅需一分钟。但是,如果某些较早的调用超出了截止日期,并且较晚的调用比60/(N-1)花费的时间少得多,则此算法将显示“追赶”行为。即使sleepAmount较小,也可以通过休眠至少一个最小量来部分解决此问题。

© www.soinside.com 2019 - 2024. All rights reserved.