3

In threads when dealing with cancelation, you often you see code like this

while (!shutdown) {
  .. do something, if a blocking call, then it will throw the interrupted exception
  try { .. some more ... } 
  catch (InterruptedException e) { 
    shutdown = true; 
  }
}

What I want to know is, is this, or why is this, better than doing this

try {
  while (true) {
    .. do something, if a blocking call, then it will throw the interrupted exception
    if (Thread.interrupted()) throw new InterruptedException();
  }
} catch (InterruptedException e) {
  .. clean up, let thread end
}

The way I see it is that in the latter case you don't need to bother with the shutdown var at all.

sksamuel
  • 16,154
  • 8
  • 60
  • 108

4 Answers4

7

In the first version, you can share the shutdown flag (or a similar shutdown mechanism) with the calling code, allowing it to attempt a completely graceful shutdown just by setting the flag, without interrupting the thread - possibly falling back to interruption if the graceful shutdown fails.

I wouldn't suggest using thread interruption as your only shutdown mechanism.

(Equally, be careful with how you handle the shared flag, of course. You'll need to make it thread-safe; a volatile variable would probably be enough in simple cases.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

I think the second way is cleaner. Here's a good article on the same point which also points out some I/O considerations around thread interruption. http://www.javaspecialists.eu/archive/Issue056.html

2

You don't use exceptions as a way to exit from a condition (at least not typically, and it is a practice best to be avoided.) An exception is for ... cue drums ... announce exceptions, errors, situations and conditions that are typically or potentially bad.

A shutdown is not (typically) an error condition, so at least from that philosophical/design point of view, I would prefer the first option using the shutdown flag variable.

Also, the flag can be externalized as a read-only property (say, as a getter). Then components external to the thread can see whether the thread is still active (if they have logic that legitimately depends on that.)

On a personal note, I dislike that Java uses InterruptedException as it is typically not an exception per say, but a signal, typically a normal and expected signal. Oh well.

luis.espinal
  • 10,331
  • 6
  • 39
  • 55
1

I would suggest you use finally to cleanup a thread (as this is always called) and not to throw an exception just to break a loop. try

try {
  while (!Thread.interrupted()) {
    .. do something, if a blocking call, then it will throw the interrupted exception
  }
} catch (InterruptedException e) {
  // handle exception
} finally {
  .. clean up, let thread end
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130