Reputation: 7890
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?
Upvotes: 3
Views: 9047
Reputation: 71
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?
Upvotes: 4
Reputation: 32949
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()
.
Upvotes: 6