9

if i put a thread to sleep in a loop, netbeans gives me a caution saying Invoking Thread.sleep in loop can cause performance problems. However, if i were to replace the sleep with join, no such caution is given. Both versions compile and work fine tho. My code is below (check the last few lines for "Thread.sleep() vs t.join()").

public class Test{

    //Display a message, preceded by the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    private static class MessageLoop implements Runnable {
        public void run() {
            String importantInfo[] = {
                "Mares eat oats",
                "Does eat oats",
                "Little lambs eat ivy",
                "A kid will eat ivy too"
            };
            try {
                for (int i = 0; i < importantInfo.length; i++) {
                    //Pause for 4 seconds
                    Thread.sleep(4000);
                    //Print a message
                    threadMessage(importantInfo[i]);
                }
            } catch (InterruptedException e) {
                threadMessage("I wasn't done!");
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {


        //Delay, in milliseconds before we interrupt MessageLoop
        //thread (default one hour).
        long patience = 1000 * 60 * 60;

        //If command line argument present, gives patience in seconds.
        if (args.length > 0) {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }

        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        //loop until MessageLoop thread exits
        while (t.isAlive()) {
            threadMessage("Still waiting...");
            //Wait maximum of 1 second for MessageLoop thread to
            //finish.
            /*******LOOK HERE**********************/
            Thread.sleep(1000);//issues caution unlike t.join(1000)
            /**************************************/
            if (((System.currentTimeMillis() - startTime) > patience) &&
                    t.isAlive()) {
                threadMessage("Tired of waiting!");
                t.interrupt();
                //Shouldn't be long now -- wait indefinitely
                t.join();
            }

        }
        threadMessage("Finally!");
    }
}

As i understand it, join waits for the other thread to complete, but in this case, arent both sleep and join doing the same thing? Then why does netbeans throw the caution?

jmj
  • 237,923
  • 42
  • 401
  • 438
Dhruv Gairola
  • 9,102
  • 5
  • 39
  • 43
  • this http://stackoverflow.com/questions/3535754/netbeans-java-new-hint-thread-sleep-called-in-loop may help – urmalp Dec 30 '10 at 11:28
  • 1
    @prateek yeah, i actually saw that thread before posting. however, that question is a completely different one (i know the cause of the caution but don't know why it does so in this case). thanks for your input though! much appreciated! – Dhruv Gairola Dec 30 '10 at 12:26

3 Answers3

33

There is a difference between join() and sleep(). join() will wait until the timeout expires or the thread finishes. sleep() will just wait for the specified amount of time unless interrupted. So it is perfectly possible for join() to return much faster than the specified time.

The reason why Netbeans warns you about sleep() and not about join() is precisely that difference. join() waits for something meaningful while sleep() just sits there doing nothing. If you aren't waiting for something, then why would you want to wait at all? It is rarely meaningful, hence the warning.

Sergei Tachenov
  • 24,345
  • 8
  • 57
  • 73
6

That they can be used to achieve the same thing doesn't mean they are abused in the same way. People often abuse Thread.sleep() when they should really use a lock or something that blocks:

 // Allow others to notify me when there's work to do
 synchronized (lock) {
     try {
         lock.wait(); // Much better than a loop with sleep
     } catch(InterruptedException e) {
         // someone killed me
         return;
     }
 }


 // or use a BlockingQueue or similar
 Job job = queue.get();
 if (job instanceof ExitJob) return;
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • thanks for the help! i guess then my qn would be this- whats the difference here between sleep and join? looks like none to me in this case.. – Dhruv Gairola Dec 30 '10 at 10:56
  • 1
    In your case, there is no difference; Netbeans just gives a warning for `sleep()`. – Aaron Digulla Dec 30 '10 at 11:00
  • um, by "lock" you mean sleep, right? and by "better alternative", you mean better alternative in this specific case, right? – Dhruv Gairola Dec 30 '10 at 11:17
  • By lock, I mean that you create an instance of `Object` and `wait` on it until someone calls `notify`. That way, you don't waste time doing nothing. If you need to do something repeatedly, use a `Timer` instead of waiting yourself. – Aaron Digulla Dec 30 '10 at 11:33
  • not sleep.. wait method.. if you call join method of a thread , the current thread will be blocked until the joined thread finishes its job.. Well, this is the exactly you want.. – Gursel Koca Dec 30 '10 at 11:33
  • @Aaron Digulla oh yeah totally, i agree. locks are way better. i was just asking Gursel about his comment. i just wanted a conformation that theres no difference between sleep and join in this specific case. – Dhruv Gairola Dec 30 '10 at 11:51
  • 1
    @AaronDigulla Timer should not be used from Java 5 onwards. Better alternative is to use ScheduledThreadPoolExecutor ... – Inquisitive Jul 14 '12 at 17:09
2

For this case, I think that join is better alternative than using a lock.. join is simple and elegant. But if you use a lock, you should also use notify method , and synchronized block and of course you need a lock object..

join sample , calling thread code ;

t1.start();
System.out.println("waiting for thread t1");
t1.join();
System.out.println("thread t1 has finished its job");

lock sample : calling thread code ;

Object lock = new Object();

 synchronized(lock) {
  try {
      t1.start();
      System.out.println("waiting for thread t1");
       lock.wait();
      System.out.println("thread t1 has finished its job");
  }catch (InterruptedException ex) {
          e.printStackTrace();
  } 

}

Here is thread t1 code;

 synchronized(lock) {
      try {
          System.out.println("doing heavy work");
           // .....
            lock.notify();
          }catch (InterruptedException ex) {
              e.printStackTrace();
      } 

   }
Gursel Koca
  • 20,940
  • 2
  • 24
  • 34
  • thanks for your help Gursel, much appreciated. i agree, locks are definitely better. but my qn was abt sleep and join, and that both are functioning the same in this specific case. – Dhruv Gairola Dec 30 '10 at 11:53