1 2 3 Previous Next 74 Replies Latest reply: Jun 13, 2007 2:03 PM by 796440 RSS

    Thread not responding to stop()

    807605
      Hi, i'm in the midst of writing my first application, a Blackjack game. I'm having a problem with InterruptedExceptions being thrown when I call Thread.sleep() from within one of my threads.

      Is there a way I can find out which thread is being interrupted by which other thread?

      Upon running the Java debugger, i've noticed that the thread number continually increases. It gets greater as I run the application and never stops increasing, like so:

      Thread-3[1] next
      >
      Breakpoint hit: "thread=Thread-4", BlackjackPanel$CardPanel.run(), line=453 bci=
      0
      453                     if (doDealAnimation)
      Thread-4[1] next
      Here's an example of how I call stop() and the following line is still executed:
      Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=533 bci=
      417
      533                                                     stop();
      
      Thread-3[1] next
      >
      Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=534 bci=
      421
      534                                                     return;
      The complete source for this application is at: http://kouellette16.home.comcast.net/MyBlackjackGame__6-13-07.zip

      Thank you for your time.
        • 1. Re: Thread not responding to stop()
          807605
          Thread.stop() is deprecated.

          Click here to see why.
          • 2. Re: Thread not responding to stop()
            807605
            Yeeaahhh... i'm aware of that. I've already overidden the stop method.
                      private void stop()
                      {
                           if (thread != null)
                           {
                                thread.interrupt();
                                thread = null;
                                //System.out.println("Stopping thread");
                           }
                      }
            Thanks for the super-helpful post.
            • 3. Re: Thread not responding to stop()
              abillconsl
              try:
              public class OuterClass {
                private InnerThread it;
              /* ... */
                private class InnerThread  extends Thread {
                  boolean keepGoing;
                  private InnerThread() {
                     keepGoing = true;
                  }
                  /* ... */
                  public void run() {
                    while ( keepGoing ) {
                      /* ... */
                    }
                  }
                  public void stopIt() {
                    keepGoing = false;
                  }
                }
              /* ... */
                public void someOtherMethodThatUsesInnerThread() {
                  /* ... */
                  it = new InnerThread();
                  it.start();
                  doSomeOtherMethodThatProducesSomeOutcome();
                }
                private void doSomeOtherMethodThatProducesSomeOutcome() {
                  /* ... */
                  it.stopIt();
                }
              }
              • 4. Re: Thread not responding to stop()
                796440
                Yeeaahhh... i'm aware of that. I've already overidden
                the stop method.
                [snip]
                Thanks for the super-helpful post.
                Wow. Somebody's got his tampon stuck crossways today.
                • 5. Re: Thread not responding to stop()
                  807605
                  Yeeaahhh... i'm aware of that. I've already overidden
                  the stop method.

                  Thanks for the super-helpful post.
                  Then you're talking about a Runnable, right? Thread.stop() is also final, so you can't override it. If you're implementing a Runnable, then you're not overriding stop().

                  Thanks for the smart-ass comment, though.
                  public class DieThread {
                  
                      class NiftyThread implements Runnable {
                  
                          private boolean die;
                          private int blah;
                  
                          public void run() {
                              while (!die && blah < 100) {
                                  System.out.printf("\b\b\b\b\b\b\b\b\b\bBlah. %3d%%", blah++);
                                  try {Thread.sleep(10);} catch (InterruptedException e) {/*gulp*/}
                              }
                          }
                  
                          public void stop() {
                              die = true;
                          }
                      }
                  
                      public DieThread() {
                  
                          NiftyThread myThread = new NiftyThread();
                          (new Thread(myThread)).start();
                  
                          try {Thread.sleep(1000);} catch (InterruptedException e) {/*gulp*/}
                          myThread.stop();
                  
                      }
                  
                      public static void main(String[] args) {
                          new DieThread();
                      }
                  
                  }
                  EDIT: How about doling out some Dukes, there, tough guy? I'm pretty sure abillconsl solved your problem for you.
                  • 6. Re: Thread not responding to stop()
                    abillconsl
                    Thanks for that kev ... OP, why not split em up for us.
                    • 7. Re: Thread not responding to stop()
                      807605
                      In my opinion and considering the deprecations of the Thread API, I consider using any idea of "stopping" or "killing" a thread to be bad practice. Here's the scenario I would prefer:
                      public class NiceRunnable implements Runnable {
                          public void run() {
                              try {
                                  for(int i = 0; i < 100 && !Thread.currentThread().isInterrupted(); ++i) {
                                      System.out.println(i);
                                      Thread.sleep(10);
                                  }
                              } catch(InterruptedException e) {
                                  //We must not forget that catching the InterruptedException clears the interrupted flag
                                  //Thus the try/catch has to be outside of the loop
                              }
                          }
                      }
                      Using this kind of Runnable, all we need to do to get the Thread to stop execution is
                      Thread t = new Thread(new NiceRunnable());
                      t.start();
                      t.interrupt();
                      And if we wish to block the execution until we are sure that the Thread has completely stopped, we only need to call t.join().
                      • 8. Re: Thread not responding to stop()
                        807605
                        Oh and before anyone asks... The reason for using interrupt instead of adding yet another boolean is that the Java API already relies on the interrupted flag to break out of blocking calls such as ServerSocket.accept(), InputStream.read() and so on... So the interrupt solution will work wherever you are inside the execution of a Runnable. Blocked on an API call or running through your own loops.
                        • 9. Re: Thread not responding to stop()
                          796440
                          Oh and before anyone asks... The reason for using
                          interrupt instead of adding yet another boolean is
                          that the Java API already relies on the interrupted
                          flag to break out of blocking calls such as
                          ServerSocket.accept(), InputStream.read()
                          The downside is that the interrupt can occur at any point, so it can be harder to clean up. The boolean lets you control exactly when the thread will be told it's time to stop.
                          • 10. Re: Thread not responding to stop()
                            807605
                            The downside is that the interrupt can occur at any
                            point, so it can be harder to clean up. The boolean
                            lets you control exactly when the thread will be told
                            it's time to stop.
                            The interrupt can occur at any point, but since you're the one responsible for checking the interrupted flag, it is easy to figure out what cleanup has to be done. Unlike some believe, interrupt doesn't actually stop a Thread, it just raises a flag which should be queried regularly by any Thread so that it knows it has been requested to stop in a deterministic manner.

                            An example which illustrates this is the following:
                            public class NastyRunnable implements Runnable {
                                public void run() {
                                    while(true) {
                                        System.out.println("haha I'm still alive");
                                    }
                                }
                            }
                            Try running this in a thread and then interrupting it and you'll see the result.
                            • 11. Re: Thread not responding to stop()
                              796440
                              The downside is that the interrupt can occur at
                              any
                              point, so it can be harder to clean up. The
                              boolean
                              lets you control exactly when the thread will be
                              told
                              it's time to stop.
                              The interrupt can occur at any point, but since
                              you're the one responsible for checking the
                              interrupted flag, it is easy to figure out what
                              cleanup has to be done. Unlike some believe,
                              interrupt doesn't actually stop a Thread, it just
                              raises a flag which should be queried regularly by
                              any Thread so that it knows it has been requested to
                              stop in a deterministic manner.
                              I know there are some conditions when it raises the flag and some when it throws the exception, but I haven't used it for a while, so I don't recall the details.

                              If it only throws the exception when it's in a blocking call, else raises flag, then yes, we can dispense with the additional boolean.

                              ...


                              Okay, I just looked. InterruptedException and the various I/O exceptions that can be thrown by interrupt() are checked, so they can't occur anywhere in your code where you're not expecting them.

                              However, if you want pure flag behavior--that is, if the interrupt occurs while blocked and you want to ignore it, complete that read or whatever, complete that iteration of your loop, and just wrap up at the end, then you'll need to set another flag in the catch block. Or maybe just interrupt() again, which will raise the flag this time?
                              • 12. Re: Thread not responding to stop()
                                807605
                                Exactly, the InterruptedException is the way the Java API uses to break out of its blocking methods. It won't be thrown in your face out of the blue.

                                As for allowing the completion of an iteration of a loop before really interrupting your Thread, you will in fact need another internal flag of yours. Although this still is better than the previous approach with a custom stop method since calling interrupt will allow you to break out of your own code, or to break out of a blocking API call. On the other hand, the stop method shown earlier wouldn't make it possible to break out of a blocking API call.

                                Finally, another advantage of relying on "interrupt" to stop a Thread is that you can benefit from the abstraction of handling a Collection of Threads and stop them without knowing any specific implementation details such as a custom stop method.


                                I think I'll write an sdnshare article on the subject ;)
                                • 13. Re: Thread not responding to stop()
                                  abillconsl
                                  Boise I da know ... Joshua Bloch seems to use the older method alot in his section on Threading.
                                  • 14. Re: Thread not responding to stop()
                                    796440
                                    As for allowing the completion of an iteration of a
                                    loop before really interrupting your Thread, you will
                                    in fact need another internal flag of yours.
                                    Nope. Just call interrupt() in your catch block and test interrupted() at the end (or beginning) of your loop. See code below.

                                    :-)


                                    Finally, another advantage of relying on "interrupt"
                                    to stop a Thread is that you can benefit from the
                                    abstraction of handling a Collection of Threads and
                                    stop them without knowing any specific implementation
                                    details such as a custom stop method.
                                    Although you do have to know that they respond to interrupt properly. Still a good point though.
                                    import java.util.*;
                                    
                                    public class InterruptTest {
                                      public static void main(String[] args) throws Exception {
                                        Random rand = new Random();
                                        while (true) {
                                          Thread th = new Thread(new Task());
                                          th.start();
                                          Thread.sleep(rand.nextInt(200) * 10);
                                          System.out.println("main interrupting task");
                                          th.interrupt();
                                          th.join();
                                        }
                                      }
                                    }
                                    
                                    class Task implements Runnable {
                                      public void run() {
                                        while (true) {
                                          System.out.println(new Date());
                                    
                                          try {
                                            Thread.sleep(250);
                                          }
                                          catch (InterruptedException exc) {
                                            System.out.println("Interrupted, re-interrupting");
                                            Thread.currentThread().interrupt();
                                          }
                                    
                                          for (int ix = 0; ix < 200000000; ix++) {
                                            int jx = ix * ix;
                                            if (ix % 1000000 == 0) {
                                              Thread.yield();
                                            }
                                          }
                                          
                                          if (Thread.interrupted()) {
                                            System.out.println("Interrupted, ending");
                                            break;
                                          }
                                        }
                                      }
                                    }
                                    Wed Jun 13 11:18:34 PDT 2007
                                    main interrupting task
                                    Interrupted, ending
                                    Wed Jun 13 11:18:38 PDT 2007
                                    main interrupting task
                                    Interrupted, re-interrupting
                                    Interrupted, ending
                                    Wed Jun 13 11:18:41 PDT 2007
                                    main interrupting task
                                    Interrupted, ending
                                    Wed Jun 13 11:18:44 PDT 2007
                                    main interrupting task
                                    Interrupted, ending
                                    Wed Jun 13 11:18:47 PDT 2007
                                    We can see that both the InterruptedException being caught and re-raising the flag by us calling interrupt() and the flag being raised by interrupt() being called when we're not blocking can be handled by checking interrupted() at the end of the loop.
                                    1 2 3 Previous Next