tags:

views:

669

answers:

7

Hi,

Is there a way I can do a for loop for a certain amount of time easily? (without measuring the time ourselves using System.currentTimeMillis() ?)

I.e. I want to do something like this in Java:

int x = 0;
for( 2 minutes )  {
   System.out.println(x++);
}

Thanks

A: 

No. That is sort of a strange request considering how simple it would be to simply write a function that uses System.currentTimeMillis() (or whichever time function you choose). More context of the situation might be in order.

Joe Philllips
+0.5 for beating me by 23 seconds. +0.5 for pointing out oddity of the request.
@MaxGuernseyll - actually, calling `System.currentTimeMillis()` can be rather expensive. On some platforms, it will entail making a system call; i.e. hundreds of machine instructions.
Stephen C
-1 - this is not a silly question at all.
Stephen C
@Stephen C, I never said it was silly
Joe Philllips
Strange request doesn't imply silly question? If you say so ... Either way, "no" is clearly an incorrect answer.
Stephen C
@Stephen On average, how many system calls are made in 1 second if we use System.currentTimeMillis() ? And which platform performs better, i.e. least system calls made?
portoalet
@portolet - I cannot give you definitive answers to these questions.
Stephen C
A: 

I don't think there is a way to loop for a certain period of time without checking to see if you've looped for a certain period of time.

-1 - this is not correct.
Stephen C
Well someone, somewhere, has to check the time. Even if you use a ScheduledFuture or TimerTask or even a Quartz component, inside that code there will be a timing mechanism for sure.
Adriaan Koster
@Adriaan - not necessarily. On Windows and Linux the C sleep library function is implemented as a syscall; see http://cboard.cprogramming.com/c-programming/109721-sleep-system-call.html . And I expect that Java Thread.sleep(...) calls the C library function under the covers.
Stephen C
@Stephen C: I think you are smoking too much crack if you think that the relevant syscall doesn't have something to do with the time...
@MaxGuernseylll - of course the sleep syscall has *"something to do with time"*. But the mechanism is not inside the code of `ScheduledFuture` etc. It is in the OS kernel. And it most certainly does **NOT** entail *"checking to see if you've looped for a certain period of time"*.
Stephen C
@MaxGuernseylll - BTW, I flagged your comment as offensive. Kindly refrain from implying that I use illegal drugs.
Stephen C
@Stephen C: BTW, yawn. Kindly grow up?
@Max @Stephen does a mod have to lock a post?
Will
A: 

Depending on your use case either of the two sleep() methods in class Thread might fit the bill, but it sounds like you have to fuss with System.currentTimeMillis(), which seems strange.

Thread thread = Thread.currentThread();
thread.sleep(10);      // 10 milliseconds
thread.sleep(12, 345); // 12 milliseconds and 345 nanoseconds.
Jim Ferrans
Unfortunately, Thread.sleep takes a SUGGESTED time to sleep as an argument... it should definitely sleep at LEAST that many ms, not exactly. You'll still want to check to see how much time has actually elapsed.
Bill James
A: 

Loops iterate over value comparison and not for duration. So without yourself assigning and comparing the system time, you cannot do it. If however you wish it be intuitive, then you can have a function that internally uses milliseconds, but takes Minutes as argument and use it.

And No, you cannot use threads or the sleep method in it, because that does not ensure the exact time. If your processor is busy with some other thread after the given time elapses, then your thread will continue to wait.

Vaishak Suresh
+8  A: 

No, there isn't a built-in construct which does that.

I want to point out that you should not use System.currentTimeMillis() for performing, or delaying, a task for a specified time period. Instead use System.nanoTime(). The former method is inaccurate in Windows, while the latter method is accurate regardless of OS. You can use TimeUnit enum to easily go between time in milliseconds, or any other time unit, to time in nanoseconds.

        for (long stop=System.nanoTime()+TimeUnit.SECONDS.toNanos(2);stop>System.nanoTime();) {
        /*
         * Hammer the JVM with junk
         */
        }
Tim Bender
Thanks. Just curious now about how much time the time checking takes.
portoalet
Oh no. Using nanoseconds does NOT make it valid to waste CPU cycles like that! Never ever program a loop, monitor the time and do - nothing! Instead: use Thread.sleep(...) do allow the system to do *useful* things while you don't want anything from it!!
Zordid
@Zordid - The OP wants to do something useful during this loop, hence the comment I placed in the loop.@portoalet - I'm not sure, it just retrieves the high-resolution timer as opposed to another timer. So it should be the same as System.currentTimeMillis.
Tim Bender
Well, it's true that `System.currentTimeMillis()` has a coarser resolution than `nanoTime()`, but it's still ~10-15ms. So unless you want to measure in the ms range, `System.currentTimeMillis()` is perfectly OK. Also I think `System.currentTimeMillis()` is somewhat faster than `nanoTime()` (though this depends on the JVM and will not usually make a difference).
sleske
+5  A: 

I think that this is what you want:

private final Thread thisThread = Thread.current();
private final int timeToRun = 120000; // 2 minutes;

new Thread(new Runnable() {
    public void run() {
        sleep(timeToRun);
        thisThread.interrupt();
    }).start();

while (!Thread.interrupted()) {
    // do something interesting.
}

This avoids doing repeated syscalls to get the system clock value (which can be rather expensive) and polls the current thread's interrupted flag instead (much cheaper).

EDIT

There is actually no safe alternative to polling the clock or polling a flag. In theory, you could modify the above fragment to call the deprecated Thread.stop() method instead of Thread.interrupt().

(I do NOT recommend using Thread.stop() and friends. They are flawed, and dangerous to use. I'm just posing this as a theoretical alternative.)

EDIT 2

Just to point out that using Thread.interrupt() has the advantages over setting a shared flag:

  • Thread.interrupt() will cause certain blocking I/O and synchronization methods to unblock and throw a checked exception. Updating a shared flag won't do this.

  • Some third-party libraries also check the interrupt flag to see if they should stop what they are currently doing.

  • If your loop involves calls to other methods, etc, Thread.interrupt() means that you don't need to worry about those methods can access the flag ... if they need to.

EDIT 3

Just to add that sleep(N) is not guaranteed to wake the sleeping thread up after exactly N milliseconds. But under normal circumstances, it will be reasonably close.

Stephen C
+1 for a decent alternative
Tim Bender
+1  A: 
matsev