1

I was writing a program of thread that contains a loop that sleeps for 30 seconds and the loop executes until a “shutdown” flag is set to true on the runnable object executing in the thread.

class MyThread extends Thread{
//set this to true to stop the thread
volatile boolean shutdown = false;

 public void stopMe() {
   shutdown=true;   
 }
 public void run () {
      while (!shutdown) {
      // continue processing
      try {
          Thread.sleep(30000);
      } catch (InterruptedException e) {}
     }
  }
}

But when the shutdown flag is set to true, will the thread exit immediately? What if it is in the sleep call? How can the thread be woken up immediately by another thread? Please help to get answers to these questions as am learning threading

3 Answers3

2

When the run method of a thread ends, the thread also end.

To answer your second question, you must take care about the sleeping part.


JLS 17.3. Sleep and Yield

It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call to Thread.sleep or Thread.yield, nor does the compiler have to reload values cached in registers after a call to Thread.sleep or Thread.yield.

For example, in the following (broken) code fragment, assume that this.done is a non-volatile boolean field:

while (!this.done)
    Thread.sleep(1000);

The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done.

Note that in your case, it is correct as your flag is volatile, this is just a warning.

As for your final request, you can wake up a sleeping thread using Thread#interrupt. Note that interrupting a sleeping thread will throw an InterruptedException so make sure to handle it.

Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
0

During the call to Thread.sleep() the thread can get interrupted. You've had to catch that exception in your code. So if you want to stop your Thread even while it is waiting you'd have to do something like:

MyThread myThread = new MyThread();
myThread.run();

//some time later we want to stop myThread

myThread.stopMe(); //sets the flag
myThread.interrupt(); //wakes the thread up if it is sleeping
myThread.join(); //wait for myThread to finish
brain
  • 5,496
  • 1
  • 26
  • 29
0

While the simple Thread.interrupt() answers the original question, this solution does not extend well to threads doing some real stuff when not sleeping. In that case, interrupt delivered in a wrong moment may mishandled by code we do not control. (It shouldn't, but I saw a few of real-life examples when this happens.)

So I would actually "abuse" locks to implements "interruptible sleep"

class MyThread extends Thread {

  private final Object sleepLock = new Object();

   //set this to true to stop the thread
   boolean shutdown = false;

   public void stopMe() {
     synchronized (sleepLock) {
         shutdown = true;
         sleepLock.notifyAll();
     }
   }

   private void sleepCancellably(long millis) throws InterruptedException {
      long sleepEnd = System.currentTimeMillis() + millis;
      synchronized (sleepLock) {
         while (!shutdown) {
           long remaning = sleepEnd - System.currentTimeMillis();
           if (remaining <= 0) {
               break;
           }
           sleepLock.wait(remainig); 
         }
      }
   }

 public void run () {
      while (!shutdown) {

        // when doing some important stuff, stopMe() want interrupt us
        doSomeImportantStuff();

        // continue processing
        try {
            sleepCancellably(30000);
        } catch (InterruptedException e) {
            // not expected. log.errror(e) or e.printStackTrace()
        }
     }
  }
}
Piotr Findeisen
  • 19,480
  • 2
  • 52
  • 82