I have some experience of using the Java interrupt mechanism to fullfill my work, but currently I am not that clear about when should I set the interrupt status of the current thread and when should I throws InterruptedException?
And, in order to make it more clearer for you, here is the sample that I've previously coded.
This is the code before I start my work:
/*
* Run a command which locates on a certain remote machine, with the
* specified timeout in milliseconds.
*
* This method will be invoked by means of
* java.util.concurrent.FutureTask
* which will further submmited to a dedicated
* java.util.concurrent.ExecutorService
*/
public void runRemoteSript(String command, long timeout) {
Process cmd = null;
try {
cmd = Runtime.getRuntime().exec(command);
boolean returnCodeOk = false;
long endTime = System.currentTimeMillis() + timeout;
// wait for the command to complete
while (!returnCodeOk && System.currentTimeMillis() < endTime) {
// do something with the stdout stream
// do something with the err stream
try {
cmd.exitValue();
returnCodeOk = true;
} catch (IllegalThreadStateException e) { // still running
try {
Thread.sleep(200);
} catch (InterruptedException ie) {
// The original code just swallow this exception
}
}
}
} finall {
if (null != cmd) {
cmd.destroy();
}
}
}
My intention is to interrupt the command as some of the remote scripts consumes a lot of time before finishing. Thus the runRemoteScript could completed or manually stopped. And here is the updated code:
public void cancel(String cmd) {
// I record the task that I've previously submitted to
// the ExecutorService.
FutureTask task = getTaskByCmd(cmd);
// This would interrupt the:
// Thread.sleep(200);
// statement in the runRemoteScript method.
task.cancel(true);
}
public void runRemoteSript(String command, long timeout) {
Process cmd = null;
try {
cmd = Runtime.getRuntime().exec(command);
boolean returnCodeOk = false;
long endTime = System.currentTimeMillis() + timeout;
// wait for the command to complete
**boolean hasInterruption = false;**
while (!returnCodeOk && System.currentTimeMillis() < endTime) {
// do something with the stdout stream
// do something with the err stream
try {
cmd.exitValue();
returnCodeOk = true;
} catch (IllegalThreadStateException e) { // still running
try {
Thread.sleep(200);
} catch (InterruptedException ie) {
// The updated code comes here:
hasInterruption = true; // The reason why I didn't break the while-loop
// directly is: there would be a file lock on
// the remote machine when it is running, which
// will further keep subsequent running the same
// script. Thus the script will still running
// there.
}
}
}
// let the running thread of this method have the opportunity to
// test the interrupt status
if (hasInterruption) {
Thread.currentThread().interrupt();
}
// Will it be better if I throws a InterruptedException here?
} finall {
if (null != cmd) {
cmd.destroy();
}
}
}
The point is, is it better to set the interrupt status for calling thread to test? Or just throws a new InterrutedExeption to the caller? Are there any best practices or particular circumstants in which one of the above approach would fit better?
I would write down my understanding here, so that you could correct my if I missunderstood any of them. According to my understanding, I think the thread.interrupt() is intended for not requiring the client code to handle the interrupt and it's the client code responsibility to decide whether to test it or not, while the throws InterruptedException is a must because it is checked exception?