5

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?

Gray
  • 115,027
  • 24
  • 293
  • 354
Cratylus
  • 52,998
  • 69
  • 209
  • 339

2 Answers2

2

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.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • 1)Where/how do you use the `volatile boolean` flag you recommend?2)if `Thread B` might still be running, shouldn't `Thread A` have a way to detect it and continue "waiting" on `Thread B`? – Cratylus Jul 19 '12 at 17:35
  • @user384706 You can certainly keep going can call `join()` again. I'm just saying that it is bad form. Something is interrupting the main thread which typically means that it should exit. Maybe it should in turn interrupt the `a` thread. If you are using interrupt to be a signal to doing something then I would use a `volatile boolean` instead. – Gray Jul 19 '12 at 17:42
  • So are you saying it is a bad form because the `interupt` is in `main`?But this is a trivial code for illustration as I mentioned.If instead of `main` the interupt was in some other thread X that joins thread B, would you still consider it as bad practice?I am trying to understand your answer here – Cratylus Jul 19 '12 at 17:51
  • Something is interrupting the main thread (or Thread X). I assume it is your code doing that? The interrupt is not _in_ main, it is the main thread which is being interrupted. My point is that it is bad form to ignore the interrupt. If you are trying to use the interrupt to notify the thread in some way, I'd set a `volatile boolean` instead. – Gray Jul 19 '12 at 18:08
2

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!".

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • But if I understand correctly what you are saying the norm would be for another thread of `mine` to call `interrupt` on `Thread A` for instance. So why should I interpret this interrupt as "Danger" as you point out? – Cratylus Jul 19 '12 at 17:40
  • 1
    @user384706: `interrupt()` replaced unsafe `stop()`. Typically that method is used on shutdown or when you simply want to "kill" a thread. That's why I named this "danger", because you don't normally control your threads via this mechanism. – Tomasz Nurkiewicz Jul 19 '12 at 17:51