tags:

views:

447

answers:

10

Hello,

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.

Is there a better way?

Thanks!

+8  A: 

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.

Just waiting

Thread.sleep(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).

Repeat some code for 15s

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:

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

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.concurrent for lots of useful objects. Most methods which lock (like wait() ) have a timeout argument. A mutex might do exactly what you need.

Nick Fortescue
More than likely he wants the thread to do something for 15 seconds, so sleeping would be counterproductive.
Jason Nichols
fair point, I've extended the answer
Nick Fortescue
+2  A: 

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

Michel Kogan
A: 

The calling thread creates a new thread that will execute your code for 15 sec.

Pseudocode:

t = Create new Thread with the code that must be executed 15 sec
Start t
Sleep 15 sec
Stop t
Victor Hurdugaci
Except that stopping threads in Java is very problematics and not recommended.
Michael Borgwardt
Should I delete my post? Because I see it is an accepted answer but some say is not a good solution for Java.
Victor Hurdugaci
I think it's fine as long as you way you stop the Thread is by having it check a shared variable, rather than using Thread.kill() or similar.
Nick Fortescue
A: 

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.

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.nanoTime should not get confused by system clock changes. Use of long literal numbers is important.

Tom Hawtin - tackline
A: 

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

YuppieNetworking
A: 

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.

Alexander Pogrebnyak
Interesting - the timer value will be updated every time the kernel ticks anyway so timer operations while not free should be cheap. Doing anything in a tight loop will warm the CPU up.
Robert Christie
+1  A: 

As already mentioned by other posters, if you just want the thread to pause for some time use 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();
binil
*please* do not ignore the InterruptedException. If *something* wants to interrupt, so do it (at least exit the loop).
Carlos Heuberger
@Carlos Thanks! I edited the code to exit the loop on interruption.
binil
A: 

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.

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.

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

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

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

Code example: Fetching an advertisement with a time budget.

Steven G. Brown
A: 

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

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.

Peter Lawrey