简体   繁体   中英

CountDownLatch InterruptedException

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 the best practice for handling it?

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 current thread's interrupt flag to be set.
        Thread.currentThread().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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM