3

I have couple of objects which implement the Runnable interface and I execute them in separate Threads. Essentially in the run() method of the Runnable object I do some network activities which includes call to methods that block while waiting for input (from the network). Note that I do not have any deliberate pauses i.e. Thread.sleep() calls. Any pause is caused by calls to methods that may block.

These Runnable objects are under the control of a GUI and hence the GUI interface and one function I wish to provide to the user is the ability to end the thread executing my Runnable objects however I'm not able to understand how to do this.

One obvious means is to call the Thread.interrupt() method of the Runnable objects Thread but how is this call to the Thread method propagated through to the Runnable object? For example I cannot use try-catch, catching InterruptedException in the Runnable object does not seem to be allowed; my IDE (netbeans) complains that InterruptedException is never thrown in the run() method.

My code is below, stripped for brevity. The following lines are executed in the GUI code in the GUI thread:

digiSearch = new DigiSearch(hostIP,this);
digiSearchThread = new Thread(digiSearch);
digiSearchThread.start();

The following is my Runnable class and where I would like/need to capture the interruption of its executing thread.

public class DigiSearch implements Runnable {

private String networkAdapterIP;
private DigiList digiList;

public DigiSearch (String ipAddress, DigiList digiList){
    networkAdapterIP = ipAddress;
    this.digiList = digiList;
}
@Override
public void run() {
    
    try{
        /*
 * Do some network and other activities here which includes calling some blocking methods.  However I would like to interrupt the run() method if possible by calling Thread.interrupt()
*/
                    
            
    }  catch (Exception ex){
       digiList.digiListException(ex);
    } catch (Throwable t){
       System.out.println("Search thread interrupted");
    }
}

}

Could someone enlighten me on how I can achieve this or perhaps resolve my misunderstanding of interrupting threads?

Community
  • 1
  • 1
D-Dᴙum
  • 7,689
  • 8
  • 58
  • 97

2 Answers2

6

Do you have any blocking methods that throw IOException? If so, this is probably your InterruptedException placeholder. Many of these method were written before InterruptedException was introduced and so rather than update the interface which would break legacy code, they wrap the InterruptedException in an IOException.

If this is not the case you are kinda stuck. For example, if you write a Runnable that creates an infinit loop that just does work and never sleeps, interrupting this thread will not result in an InterruptedException. It is the responsibilily of the Runnable to regularly check Thread.interrupted().

John B
  • 32,493
  • 6
  • 77
  • 98
  • To see what exception, if any, is thrown in the Runnable.run() method I placed a catch for the high level Exception class. Nothing happens though, i.e. no exception whatsoever is caught in the Runnable object. I don't think what I want to achieve is possible in Java and the only way is as you say keep checking a flag. This is pretty poor though because if run() is currently blocked then the flag won't be checked. It's perhaps just a failing in Java? – D-Dᴙum Nov 20 '12 at 14:46
  • Is it possible to get the object-method a Thread is currently executing? – D-Dᴙum Nov 20 '12 at 14:49
  • Check out this post, it is very similar: http://stackoverflow.com/questions/13415969/spring-resttemplate-not-allowing-cancel-interruptedexception – John B Nov 20 '12 at 14:50
  • 1
    Not as far as I know, and even if you did there is a good chance that by the time you determined the class, that class would no longer be executing. – John B Nov 20 '12 at 14:50
  • John B, I appreciate your answer and it is of course correct but I decided to mark ar_blues' reply as my accepted answer because I thought it had a little bit more information in there plus as he/she is a new comer to stackoverflow I thought such a good answer as theirs deserves credit. I think your good reputation has already been established :-) – D-Dᴙum Nov 24 '12 at 08:41
4

Couple of points to note here:

1) While I agree it is useful to have a feature for user to stop execution of a thread, I recommend thinking about the action that the thread is already doing. Is it possible to rollback the action? Is it possible to ignore the action and just stop execution?

2) Thread.stop() and Thread.destroy() etc are deprecated methods (http://docs.oracle.com/javase/6/docs/api/)

So how does one normally interrupt thread execution? Enter volatile state variables.

public class MyClass implements Runnable {
    private volatile boolean isAlive=true;

   /**
    * Request thread stop by calling requestThreadStop() externally.
    */
    public void requestThreadStop() {
        isAlive = false;
    }

    @Override
    public void run() {
        while(isAlive) {
            //Do All your thread work
            //if isAlive is modified, the next iteration will not happen
        }
    }
}

For many use cases, the above implementation works. However, if the work inside the run() method loop is only a single iteration and can block for significant amount of time, the user has to wait until the operation completes.

Is there a way to silently discard the execution of a thread almost immediately once the user requests for termination from the GUI? Maybe. You will have to explore using Threadpools for that. Using the ExecutorService, you can provide hooks to shutdown() and shutdownNow() methods.

To avoid repetition, you can find more about this feature of threadpools from this previoud stackoverflow post How to stop the execution of Executor ThreadPool in java?

Community
  • 1
  • 1
ar_blues
  • 71
  • 1
  • 1
    Thread.sleep is not deprecated - you probably meant Thread.stop(). And the standard way to interrupt thread execution is through the interruption process, which would consist for the Runnable to check the interrupted status on a regular basis. – assylias Nov 20 '12 at 15:30
  • Yes, my run() method does not loop, it just has a single block of code execution (it in facts just uploads a data file to a remote server). There would be no problem just stopping this upload immediately in fact this is my desired operation and what I want to achieve.. it's just how to go about achieving it. Your comments have been handy, I will investigate what you suggest. Thanks – D-Dᴙum Nov 20 '12 at 16:25
  • Yes, I meant Thread.stop(). Seems like it has already been edited. Thanks. – ar_blues Nov 21 '12 at 15:19
  • I am leaning towards @JohnB solution. As long as you keep checking `Thread.interrupted` you probably don't even need that `isAlive` variable – Stackee007 Jan 19 '17 at 21:55