Cratylus
Cratylus

Reputation: 54094

Best way to handle exception when joining a thread

For some reason I am confused over the following:
Assume that I have Thread A that absolutely needs to execute after Thread B has completed its processing.
A way to do this would be by Thread A joining Thread B.
Trivial example:

public class MainThread {  
    public static void main(String[] args){   
        Thread b = new Thread (new SomeRunnable(args[0]));  
        b.start();  
        try {   
            b.join();   
        } catch(InteruptedException e) {  
        }  
        // Go on with processing  
    }
}

My question is the following: What is the proper way to handle the exception in such a case?

In various example I have seen, even in text-books, the exception is ignored.
So if Thread A needs to be sure that Thread B is completely finished before proceding, if I end up in the catch due to an exception, can it be the case that Thread B may still actually be runnable/running? So what is the best way to handle this exception?

Upvotes: 6

Views: 4642

Answers (2)

Gray
Gray

Reputation: 116908

What is the proper way to handle the exception in such a case?

Any time you get an InterruptedException the current thread should consider itself to be interrupted. Typically, that means that the thread should clean up after itself and exit. In your case, the main thread is being interrupted by another thread and should probably interrupt the Thread a that it started in turn, and then quit.

Although it is up to you whether the interrupt should be ignored I would suggest that it is a bad practice. If you were using the interrupt as some sort of signal to the thread then I would instead set some volatile boolean flag.

In terms of best practice when catching InterruptedException, typically I do:

try {
    ...
} catch(InterruptedException e){  
    // a good practice to re-enable the interrupt flag on the thread
    Thread.currentThread().interrupt();
    // in your case you probably should interrupt the Thread a in turn
    a.interrupt();
    // quit the thread
    return;
}

Since catching the InterruptedException clears the interrupt flag for the thread, it is always a good idea to re-enable the interrupt flag in the catch block.

In various example I have seen, even in text-books, the exception is ignored.

Indeed. It is very bad practice to ignore any exception but it happens all of the time. Don't give into the dark forces!

can it be the case that Thread B may still actually be runnable/running?

Thread B can certainly still be running. It is the main thread that is calling the join() that has been interrupted.

Upvotes: 2

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340933

First of all you must understand what causes this exception to be thrown. Calling stop() on a thread is currently deprecated, instead when you want to stop a thread you are interrupting it by calling thread.interrupt(). This has no impact on a thread (!), the thread must explicitly check interrupted flag once in a while and stop processing gracefully.

However if the thread sleeps, waits on a lock or on another thread (by using join() like in your example) it cannot check this flag immediately or often enough. In these cases JVM will throw an exception from blocking method (let it be join()) signalling your thread that someone just tried interrupting it. Typically you can ignore that exception (meaning - do not log it) - it's the side effect that matters. For example breaking out of the loop:

public void run() {
    try {
        while(!isInterrupted()) {
            Thread.sleep(1000);
            //...
    } catch(InterruptedException e) {
        //no need to log it, although it's a good idea.
    }
}

It's not a problem that you didn't log that exception - but you escaped from the loop, effectively terminating the thread.

Now back to your question. When your Thread A is interrupted it means some other thread requested terminating it, probably because the whole JVM shuts down or web application is being undeployed. In this case you shouldn't be doing anything except cleanup.

Moreover it most likely means Thread B is still running. But what JVM is trying to say is: "Danger! Danger! Stop waiting for whatever you were waiting for and run!".

Upvotes: 2

Related Questions