views:

50

answers:

2

I am using the CountDownLatch to synchronize an initialization process between two threads and i was wondering about the proper handling of the InterruptedException that it might throw.

the code i initially wrote was this:

    private CountDownLatch initWaitHandle = new CountDownLatch(1);
    /**
     * This method will block until the thread has fully initialized, this should only be called from different threads  Ensure that the thread has started before this is called.
     */
    public void ensureInitialized()
    {
        assert this.isAlive() : "The thread should be started before calling this method.";
        assert Thread.currentThread() != this, "This should be called from a different thread (potential deadlock)";
        while(true)
        {
            try
            {
                //we wait until the updater thread initializes the cache
                //that way we know 
                initWaitHandle.await();
                break;//if we get here the latch is zero and we are done
            } 
            catch (InterruptedException e)
            {
                LOG.warn("Thread interrupted", e);
            }
        }
    }

Does this pattern make sense? Basically is it a good idea to ignore the InterruptedException just keep waiting until it succeeds. I guess i just don't understand the situations under which this would get interrupted so i don't know if i should be handling them differently.

Why would an InterruptedException get thrown here, what is a best practise for handling it?

+4  A: 

This is exactly what you should not do for an InterruptedException. An InterruptedException is basically a polite request for that thread to terminate. The thread should clean up and exit as soon as possible.

IBM has a good article posted about this: http://www.ibm.com/developerworks/java/library/j-jtp05236.html

Here's what I would do:

// Run while not interrupted.
while(!(Thread.interrupted())
{
    try
    {
        // Do whatever here.
    }
    catch(InterruptedException e)
    {
        // This will cause the interrupt flag to be set.
        Thread.interrupt();
    }
}

// Perform cleanup and exit thread.

The advantage to doing it this way is thus: If your thread is interrupted while in a blocking method, the interrupt bit will not be set and an InterruptedException is thrown instead. If your thread is interrupted while not in a blocking method, the interrupted bit will be set, and no exception will be thrown. So by calling interrupt() to set the flag on an exception, both cases are being normalized to the first case, which is then checked by the loop conditional.

As an added bonus, this also lets you stop your thread by simply interrupting it, instead of inventing your own mechanism or interface to set some boolean flag to do the exact same thing.

jdmichal
Gah I tried to fix your formatting and it did an edit conflict. I have no option to roll-back. Sorry!
Mark Peters
I rolled it back already. Thanks for the help though! I had noticed it wrong, but decided to fix it at the same time as writing the wall of text afterwards.
jdmichal
Actually no, I'm just really used to Wikipedia where you click rollback on the edit you want to undo, not on the revision you want to rollback **to**.
Mark Peters
I can add to answer from jdmichal that you should always consider what to do with your threads (essentially, logical tasks of your application) when they are interrupted -- you can try to restart/continue these tasks or rollback them and report a failure to a upper level of application.
Victor Sorokin
Thanks a lot. That article was great. I will definetly be implementing this. I guess I have been handling interrupedexceptions incorrectly for a long time.
luke
+1  A: 

If you do not foresee any legitimate reason that the Thread could be interrupted, and can't think of any reasonable reaction to it, I'd say you should do

 catch (InterruptedException e){
      throw new AssertionError("Unexpected Interruption",e);
 }

That way the application will clearly fail if such interruption happens, making it easier to discover during the testing. Then you can think about how the application should handle that, or if they are any problem in the design.

Enno Shioji