1

Am I doing something really stupid here? I am trying to execute a method every minute or so, forever, or until I stop the program.

    while(true) {
        this.doSomethingPeriodically();
        Calendar now = Calendar.getInstance();
        int minutes = now.get(Calendar.MINUTE);
        int resume = minutes + 1;
        while (now.get(Calendar.MINUTE) < resume) {
            // waiting for a minute
        }
    }
Sam McAfee
  • 10,057
  • 15
  • 60
  • 64

7 Answers7

14

This code will never leave the loop. It's an endless loop, since the Calendar instance refered to by now won't change.

Also, what you try to do here is implement busy waiting which is a very bad idea (it uses CPU time doing nothing interesting).

The correct way to sleep is to use Thread.sleep().

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • So, if I had a new Calendar instance, it'd work? But I should use sleep() anyway, huh? – Sam McAfee Sep 28 '09 at 13:42
  • Yes to both ;-) If you assigned a new Calendar instance to now inside the loop then it would work (provided you don't enter the loop in minute 59 of the hour ;-)), but you should use sleep() instead anyway. – Joachim Sauer Sep 28 '09 at 13:46
  • 1
    Understood. I would reinventing the wheel, and making it square instead of round, so to speak. Thanks! – Sam McAfee Sep 28 '09 at 13:47
  • At the risk of being pedantic, Thread.sleep() will pause your thread for *at least* a minute (and not necessarily exactly one minute). – Randy Levy Sep 28 '09 at 14:13
  • Using sleep, you just leaves the "CPU" and became available from the "stop point + 1 line" after the sleep time. In teh case of that loop, your code only work inside that loop. Use java.util.Time and java.util.TimerTask for a clear code. – Andre Pastore Sep 28 '09 at 16:14
4

Try using the Timer class instead. It's meant for this sort of thing:

Edit: I just read that there's a newer replacement for Timer: ExecutorService. I've never used it, but it seems to have some advantages:

fospathi
  • 537
  • 1
  • 6
  • 7
Scott Saunders
  • 29,840
  • 14
  • 57
  • 64
4

the simplest way for execute tasks repeteadly in java is the java.util.TimerTask and java.util.Timer api.

A simple code is:

public class PrinterTimerTask extends java.util.TimerTask {
  @Override
  public void run() {
    System.out.println( 'Current time is: ' + System.nanoTime() );
  }

  public static void main(String[] args) {
    long delay = 0;
    long period = 60000;
    java.util.Timer timer = new java.util.Timer(threadName);
    PrinterTimerTask task = new PrinterTimerTask();
    timer = new Timer("SomeThreadNameForProfiler");
    timer.schedule( task, delay, period );
  }
}

Variables: task - task to be scheduled. delay - delay in milliseconds before task is to be executed. period - time in milliseconds between successive task executions.

More info: Timer and TimerTask javadoc: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html http://java.sun.com/j2se/1.5.0/docs/api/java/util/TimerTask.html

Another example: http://www.javapractices.com/topic/TopicAction.do?Id=54

[]'s,

And Past

Andre Pastore
  • 2,841
  • 4
  • 33
  • 44
3

Try using sleep instead, as it won't cause the processor to continue working on the thread:

Thread.sleep()

    while(true) {
            this.doSomethingPeriodically();
            Thread.sleep(60000);
    }
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
Marius
  • 57,995
  • 32
  • 132
  • 151
  • 3
    You should not extend Thread (implement Runnable instead) and you should not reference static methods (such as Thread.sleep()) via a reference. – Joachim Sauer Sep 28 '09 at 13:43
  • I would also say that it is generally a better idea to use a short sleep time and rather repeat it and check if we should stop. – Svish Sep 28 '09 at 13:57
  • @Svish, that's what `InterruptedException` is for. – gustafc Sep 28 '09 at 14:10
2

It would be better to use a Timer or at least use a sleep.

tster
  • 17,883
  • 5
  • 53
  • 72
1

What you're trying to do here is called busy waiting. You are unnecessarily using huge amounts of CPU time (and you would even be using unnecessary memory if you fixed your bug and created a new Calendar instance in each loop).

What you actually want is the method Thread.sleep(), it is pretty well explained in a tutorial on sun.com.

soulmerge
  • 73,842
  • 19
  • 118
  • 155
0

It's better to use the sleep function: CurrentThread.sleep() and you specify the number of milliseconds that you want as a delay. It's better than busy waiting...

CRUSADER
  • 5,486
  • 3
  • 28
  • 64
niz
  • 19
  • 1
  • 7
  • The exact syntax is: Thread.currentThread().sleep(delay); In the parameter you specify the delay in msec... – niz Jul 05 '13 at 08:17
  • `sleep` being a static method, it is good practice to call it on the class: `Thread.sleep(...);`. – assylias Jul 05 '13 at 09:11