Adding a timeout to commands by wrapping + thread - suggestions?
Hi,
As I know this is something that is notoriously hard to get right, I
thought I would post my naiive implementation here for comments and
advice.
The problem is a common one: We have several actions that all comply
with the same interface (in this example: Command), but it turns out
that some of them may get "stuck" if e.g. a mountpoint goes missing
during execution, which may happen once in a blue moon. Therefore we
want to develop a common facility to monitor any action for excessive
time-to-complete, and either log the problem or kill the action and
report failure up the chain by an Exception.
I came up with this naiive solution:
NB: Stopwatch is a homebrew class that measures time passed since
construction in millis.
/**
* A simple command.
*/
public interface Command {
void execute();
}
/**
* A thread that runs a command.
*/
public class CommandThread extends Thread {
private Command cmd;
public CommandThread(Command cmd) {
this.cmd = cmd;
}
public void run() {
cmd.execute();
}
}
/**
* A command that sleeps for some millis.
*/
public class SleepingCmd implements Command {
private long howLongL;
public SleepingCmd(Long howLongL) {
this.howLongL = howLongL;
}
public void execute() {
try {
Thread.sleep(howLongL);
} catch (InterruptedException e) {
throw new RuntimeException("I was interrupted!");
}
}
}
public class TimeoutWrappingCmd implements Command {
private Command wrappedCmd;
private long timeoutL;
public TimeoutWrappingCmd(Command wrappedCmd, long timeoutL) {
this.wrappedCmd = wrappedCmd;
this.timeoutL = timeoutL;
}
public void execute() {
Thread cmdThread = new CommandThread(wrappedCmd);
cmdThread.start();
Stopwatch sw = new Stopwatch();
while (sw.elapsedMillisL() < timeoutL && cmdThread.isAlive())
{
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
throw new RuntimeException(
"I was interrupted while waiting to poll
encapsulated command");
}
}
if (cmdThread.isAlive()) {
cmdThread.interrupt();
}
try {
cmdThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(
"I was interrupted while waiting for encapsulated
command to join");
}
}
}
Comments?
Sincerely,
Anders S. Johansen, Royal Danish Library