Question

I have a long running task, something like:

public void myCancellableTask() {
    while ( someCondition ) {
       checkIfCancelRequested();
       doSomeWork();
    }
 }

The task can be cancelled (a cancel is requested and checkIfCancelRequested() checks the cancel flag). Generally when I write cancellable loops like this, I use a flag to indicate that a cancel has been requested. But, I know I could also use Thread.interrupt and check if the thread has been interrupted. I'm not sure which would be the preferred approach and why, thoughts?

thanks,

Jeff

Was it helpful?

Solution

Interrupt will blast the thread out of a list of specified wait conditions. Your own cancel flag will not. If you want to interrupt waits on IO and events, use interrupt. Otherwise use your own.

OTHER TIPS

One problem with using interrupt is that if you do not control all code being executed, you run the risk of the interrupt not working "properly" because of someone else's broken understanding of how to handle interrupts in their library. That is the API invisibly exports an API around its handling of interrupts which you become dependent on.

In your example, suppose doSomeWork was in a 3rd-party JAR and looks like:

public void doSomeWork() {
    try { 
        api.callAndWaitAnswer() ; 
    } 
    catch (InterruptedException e) { throw new AssertionError(); }
}

Now you have to handle an AssertionError (or whatever else the library you are using might throw). I've seen experienced developers throw all sorts of nonsense on receiving interrupts! On the other hand, maybe the method looked like this:

public void doSomeWork() {
    while (true) {
        try { 
            return api.callAndWaitAnswer() ; 
        } 
        catch (InterruptedException e) { /* retry! */ }
    }
}

This "improper handling" of interrupt causes your program to loop indefinitely. Again, don't dismiss this as ridiculous; there are a lot of broken interrupt handling mechanisms out there.

At least using your own flag will be completely invisible to any 3rd-party libraries.

It depends on the doSomeWork() implementation. Is that pure computation or does it (at any point) involve blocking API (such as IO) calls? Per bmargulies's answer, many blocking APIs in JDK are interruptible and will propagate the interrupted exception up the stack.

So, if the work entails potentially blocking activities, you need'll to take interrupts into consideration even if you decide to control the process using a flag, and should appropriately catch and handle/propagate the interrupts.

Beyond that, if relying on a flag, make sure your flag is declared with volatile semantics.

I think that it's a matter of preference in most cases. Personally I would go for the hand-made flag. It gives you more control - for example, this way you make sure that your thread doesn't leave some other object in an inconsistent state. Besides, if performance is really critical, bear in mind that using exceptions has an overhead (even if it's negligible in 99% of the cases).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top