-1
for(i=1;i<list.size();i++){
   //do something
   //For Eg: move marker to a new position on the map
} 

I want the above loop to complete all the iterations irrespective of the size of the list and also want the entire task to run for 1 minute. (60 seconds)

  • Run it in a separate thread, then kill the thread after 60 seconds. – J. Chomel Nov 13 '19 at 08:35
  • Possible duplicate https://stackoverflow.com/questions/4252187/how-to-stop-execution-after-a-certain-time-in-java – B_Osipiuk Nov 13 '19 at 08:37
  • Possible duplicate of [How to stop execution after a certain time in Java?](https://stackoverflow.com/questions/4252187/how-to-stop-execution-after-a-certain-time-in-java) – B_Osipiuk Nov 13 '19 at 08:37
  • @J.Chomel I also want the for loop to be completed, I do not want to break it after 60 secs. – Megha Santhosh Nov 13 '19 at 09:14
  • Do you want to time each call of the body to be spread out among one minute? – Mark Jeronimus Nov 13 '19 at 09:25
  • Actually your requirements are unclear. What happens when there your list contains so few elements that you need **less** than 60 seconds? What happens when you have **more** elements, and will need more than 60 seconds? – GhostCat Nov 13 '19 at 09:47
  • @GhostCatsaysReinstateMonica The max time should be 60 seconds.. if there are more elements, it should complete in 60 seconds but if there are very less elements, it should take the time accordingly.. in either case, time should not exceed 60 seconds. – Megha Santhosh Nov 14 '19 at 04:08
  • What is the point of 60 seconds then, when you want to always complete?! – GhostCat Nov 14 '19 at 05:11

5 Answers5

1

You can, for example, use System.nanoTime() to measure the duration of your loop, and then use TimeUnit.NANOSECONDS.sleep(...) to make it wait for the rest of time like this:

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);
Yuri Kovalenko
  • 1,325
  • 9
  • 19
  • `System.currentTimeMillis()` is not safe to use across clock changes or sleep mode. Only use it for absolute time, not relative time. For relative time, use `System.nanoTime()` – Mark Jeronimus Nov 13 '19 at 09:23
1

I don't really know if this is what you want but I hope this helps.

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
} 

As explanation: you iterate through the for loop and the thread waits for one second before executing the code after the TimeUnit.SECONDS.sleep(1);.
If the list's size is 60 it would therefore take a minute for the loop to end.

Edit: It has occurred to me that it might be smarter to do a try-catch around the sleep function.

THess
  • 1,003
  • 1
  • 13
  • 21
0

Check out this.

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

int i = 0;
while (System.currentTimeMillis() < end)
{
   // do something, iterate your list
   i++;

   if (i == list.size()) { // check size of the list if iteration is completed
      // if time has not yet expired, sleep for the rest of the time
      Thread.sleep(end - System.currentTimeMillis());
   }
}

Do not forget checking size of the list.

faranjit
  • 1,567
  • 1
  • 15
  • 22
0

The best possible solution is to compute the desired time first and then run the loop to that extent.

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

If you are trying to equip the CPU and keep it idle for this time the process is known as busy waiting but is not considered convenient in many cases so i recommend to use Thread.sleep(duration) for this purpose.

Would like to receive further queries from your side.

  • Suppose i have a for loop inside while, the for loop may not complete all the iterations within 1 minute according to this logic... – Megha Santhosh Nov 14 '19 at 04:22
  • @MeghaSanthosh, It depends upon the terminating condition of the for loop ...If you don't mind can you tell me what exactly will the for loop do?.. I mean what are you using it for? – Kushal Srivastava Nov 14 '19 at 04:26
  • @MeghaSanthosh, I just looked at your comment below , if you are willing to iterate through a list using a for loop ,in that case my solution may or may not work depending on the size of the list. Another thing we can do is to use the concept of multi-threading. Can you tell me the size of your list? use size() method of java.util.ArrayList to get it. – Kushal Srivastava Nov 14 '19 at 04:34
  • Hi, have you tried this? If it helps you please upvote ( ^ ) and [accept it as an answer](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). – Kushal Srivastava Nov 19 '19 at 09:02
0

To spread N amount of invocations uniformly across a minute, you'll have to set the delay in between the invocations to the value 60/(N-1). The -1 is optional but causes the first and last invocations to be exactly 60 seconds apart. (just like how a ladder with N rungs has N-1 spaces)

Of course, using sleep() with the number calculated above is not only subject to round-off errors, but also drift, because you do stuff between the delays, and that stuff also takes time.

A more accurate solution is to subtract the time at which each invocation should occur (defined by startTime + 60*i/(N-1)) from the current time. Reorder and reformulate those formulas and you can subtract the 'time that should have elapsed for the next invocation' from the already elapsed time.

Of course 'elapsed time' should be calculated using System.nanoTime() and not System.currentTimeMillis() as the latter can jump when the clock changes or the computer resumes from stand-by.

For this example I changed 60 seconds to 6 seconds so you can more easily see what's going on when you run it.

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

Of course when the task you preform per list element takes longer than 60/(N-1) seconds, you get contention and the 'elapsed time' deadlines are always exceeded. With this algorithm the total time just taking longer than a mnute. However if some earlier invocations exceed the deadline, and later invocations take much less time than 60/(N-1), this algorithm will show 'catch-up' behavior. This can be partially solved by sleeping at least a minimum amount even when sleepAmount is less.

Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
  • Thanks for your answer. But i do not want the total time taking longer than a minute.. – Megha Santhosh Nov 14 '19 at 04:16
  • You cannot escape that because all the iterations without delays in between may take more than 60 seconds if the list if long enough or if the iterations take long enough. The last paragraph is just talking about some side effects of *this* algorithm. Any algorithm you can come up with has to deal with reality in one way or another. If you can accept skipping iterations if that will bring the time down to one minute, then there's another algorithm that can do that. – Mark Jeronimus Nov 14 '19 at 13:22