views:

606

answers:

2

Hi all, trying to figure out some behavior. I've got some code that spawns one thread. It waits some amount of time, and then interrupts it, joins it and then exits the method.

.
.
.
try {
        Thread.sleep(processForMillis);
    }
    catch (InterruptedException ex) {
        // Won't happen, ignore.
    }

    for (Thread t : threads) {
        logger.debug("Interrupting Thread " + t.getName());
        t.interrupt();
    }

    for (Thread t : threads) {
        try {
            t.join(1000L);
            logger.debug("Joined Thread " + t.getName());
            logger.debug("isAlive? " + t.isAlive());
        }
        catch (InterruptedException ex) {
            // this will never happen
            logger.debug("InterruptionException while joining, but didn't expect it.");
        }
    }
} // end of method

I am currently running this with just one thread. I can see in my logs that usually, isAlive() will be false after the join. But sometimes it is still alive. The thread is sitting in a while loop:

while(!Thread.currentThread().isInterrupted()){
.
// do some blocking io stuff here
}

So what I suspect is happening is we are interrupting the thread while it is reading/processing the inputstream (blocking io) and it is taking more than the time it takes to hit the while conditional and finish the join.

So my question is, what happens to the thread? It is no longer referenced and the thread can be garbage collected, but none of of the resources are cleaned up properly, and that seems bad. Is there a better pattern for this besides switching to NIO?

A: 

interrupt() just sets a flag on the thread that it has been interrupted. Many blocking calls does not unblock when this occurs, meaning the thread is pretty much unaffected by the interrupt and keeps doing its thing(e.g. blocking on an InputStream).

I'm guessing in some cases the thread doesn't unblock and hit your while condition in the given join timeout (1 second here), in other cases the blocking call happens to complete within the timeout and the thread ends.

As long as a thread is running it will still have a reference and not be garbage collected. If the blocking call never unblocks - which could happen if it reads from e.g. a dead tcp sockets whos other end has silently disappeard, the thread might never end.

nos
Yup, that's what I suspected. Is there a good pattern to solve this problem besides NIO or increasing (or not using) the join wait time?
DanInDC
A: 

In addition to the nos's answer, to interrupt a blocking IO call you can close() its stream

axtavt