views:

95

answers:

4

I have a scenario where i want a thread to sleep for specific amount of time.

Code:

    public void run(){
        try{
            //do something
                     Thread.sleep(3000);
//do something after waking up
                }catch(InterruptedException e){
                // interrupted exception hit before the sleep time is completed.so how do i make my thread sleep for exactly 3 seconds?
                }
        }

Now how do i handle the case where the thread i am trying to run is hit with an interrupted exception before the complete of the sleep? Also does the thread wake up after being interrupted and does it go to runnable state or when is it that only after it goes to runnable does the flow go to catch block?

A: 
  1. using Sleep in my experience is usually to compensate for bad timing somewhere else in the program, reconsider!
  2. try this:

    public void run(){
            try{
                //do something
                long before = System.currentTimeMillis();
                Thread.sleep(3000);
                //do something after waking up
            }catch(InterruptedException e){
                long diff = System.currentTimeMillis()-before;
                //this is approximation! exception handlers take time too....
                if(diff < 3000)
                    //do something else, maybe go back to sleep.
                    // interrupted exception hit before the sleep time is completed.so how do i make my thread sleep for exactly 3 seconds?
            }
    }
    
  3. if you do not interrupt the sleep yourself, why would this thread be awoken ? is seems that you are doing something very wrong...

codeScriber
The interrupt can come from an external event, such as a 'graceful shutdown' request from the OS.
Tony Ennis
A: 

According to this page you'll have to code it to behave the way you want. Using the thread above your sleep will be interrupted and your thread will exit. Ideally, you'd re-throw the exception so that whatever started the thread could take appropriate action.

If you don't want this to happen, you could put the whole thing in a while(true) loop. Now when the interrupt happens the sleep is interrupted, you eat the exception, and loop up to start a new sleep.

If you want to complete the 3 seconds of sleep, you can approximate it by having, say, 10 sleeps of 300 milliseconds, and keeping the loop counter outside a while loop. When you see the interrupt, eat it, set a "I must die" flag, and continue looping until you have slept enough. Then you interrupt the thread in a controlled manner.

Here's one way:

public class ThreadThing implements Runnable {
    public void run() {
        boolean sawException = false;
        for (int i = 0; i < 10; i++) {
            try {
                //do something
                Thread.sleep(300);
                //do something after waking up
            } catch (InterruptedException e) {
                // We lose some up to 300 ms of sleep each time this
                // happens...  This can be tuned by making more iterations
                // of lesser duration.  Or adding 150 ms back to a 'sleep
                // pool' etc.  There are many ways to approximate 3 seconds.
                sawException = true;
            }
        }
        if (sawException) Thread.currentThread().interrupt();
    }
}
Tony Ennis
A: 

Why do you want to sleep for exactly 3 seconds? If it's just having to execute something after some time, try using a Timer.

Jorn
locka
+1  A: 

When your thread is hit by an interrupt it will go into the InterruptedException catch block. You can then check how much time the thread has spent sleeping and work out how much more time there is to sleep. Finally, instead of swallowing the exception, it is good practice to restore the interruption status so that code higher up the call stack can deal with it.

public void run(){

    //do something

    //sleep for 3000ms (approx)     
    long timeToSleep = 3000;
    long start, end, slept;
    boolean interrupted;

    while(timeToSleep > 0){
        start=System.currentTimeMillis();
        try{
            Thread.sleep(timeToSleep);
            break;
        }
        catch(InterruptedException e){

            //work out how much more time to sleep for
            end=System.currentTimeMillis();
            slept=end-start;
            timeToSleep-=slept;
            interrupted=true
        }
    }

    if(interrupted){
        //restore interruption before exit
        Thread.currentThread().interrupt();
    }
}
dogbane