This library extends java.lang.Thread class to provide clean and reliable thread terminating capability.
The usual method prescribed by many, to simulate thread kill, is to use a control variable which thread needs to keep checking. When thread needs to be killed, it is sent an interrupt signal and the interrupt handler sets this variable to some value to indicate that thread needs to die. This works only when thread can come out of a blocking operation like database call or accepting a socket or finishing reading a file.
Note that the default interrupt function available on Thread works only when the thread is in sleep/wait state.
There is no way to interrupt a busy thread
The new approach uses control resource and thread shutdown hook. The control resource could be an open file or database connection or anything else which is crucial to thread's normal life cycle. If you close this resource, thread dies. The programmer adds (or removes) the hooks to close these control resources.
TerminateThread class extends Thread class. It keeps a stack of terminate hooks (per instance of TerminateThread) which are added by a programmer at run time. Thus when developer invokes interrupt on TerminativeThread's instance, it checks all the available hooks and invokes each one them in the order in which they were added
Here's how you use it ...
Thread t1 = new TerminativeThread(new Worker(5080));
// Thread t1 = new Thread(new WorkerThread(5080));
t1.start();
Thread t2 = new TerminativeThread(new Worker(5081));
// Thread t2 = new Thread(new WorkerThread(5081));
t2.start();
logger.info("Sleep --");
Thread.sleep(1000 * 5);
logger.info("Calling kill --");
t1.interrupt();
logger.info("Sleep --");
Thread.sleep(1000 * 5);
logger.info("Calling kill --");
t2.interrupt();
logger.info("Inside run() --");
TerminativeThread.push(new ThreadTerminateHook() {
public void terminate() {
logger.info("Set abort = true --");
abort = true;
}
});
try {
while (!abort) { // abort is class member variable
// Test Case : Thread is waiting for a socket
/*
try {
final ServerSocket ssock = new ServerSocket(port);
TerminativeThread.push(new ThreadTerminateHook() {
public void terminate() {
logger.info("Inside ThreadShutDownHook -- ");
try {
ssock.close();
} catch (Exception e) {
}
logger.info("Leaving ThreadShutDownHook -- ");
}
});
ssock.accept();
} catch (Exception e) {
e.printStackTrace();
}
*/
// Test Case : Thread is busy reading from file (note there is no sleep!)
final BufferedReader rdr = new BufferedReader(new FileReader("c:/docs/Test.txt"));
TerminativeThread.push(new ThreadTerminateHook() {
public void terminate() {
logger.info("Close rdr --");
try {
rdr.close();
} catch (Exception e) {
}
}
});
try {
String line = null;
while ((line=rdr.readLine()) != null) {
;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
Thread.yield();
try { rdr.close(); } catch (Exception e) {}
TerminativeThread.pop();
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
TerminativeThread.clear();
}
logger.info("Leaving run() --");
Oct 30, 2011 1:28:18 PM Test test
INFO: Starting Threads --
Oct 30, 2011 1:28:18 PM Test test
INFO: Sleep --
Oct 30, 2011 1:28:18 PM Worker run
INFO: Inside run() --
Oct 30, 2011 1:28:18 PM Worker run
INFO: Inside run() --
Oct 30, 2011 1:28:28 PM Test test
INFO: Calling kill --
Oct 30, 2011 1:28:28 PM open.ejaz.tthread.TerminativeThread interrupt
WARNING: TID 10 Inside interrrupt --
Oct 30, 2011 1:28:28 PM Worker$2 terminate
INFO: Close rdr --
java.io.IOException: Read error
at java.io.RandomAccessFile.read(Native Method)
at java.io.RandomAccessFile.readLine(RandomAccessFile.java:871)
at Worker.run(Worker.java:67)
at java.lang.Thread.run(Thread.java:662)
Oct 30, 2011 1:28:28 PM Worker$1 terminate
INFO: Set abort = true --
Oct 30, 2011 1:28:28 PM Test test
INFO: Sleep --
Oct 30, 2011 1:28:28 PM Worker run
INFO: Leaving run() --
Oct 30, 2011 1:28:35 PM Test test
INFO: Calling kill --
Oct 30, 2011 1:28:35 PM open.ejaz.tthread.TerminativeThread interrupt
WARNING: TID 11 Inside interrrupt --
Oct 30, 2011 1:28:35 PM Worker$2 terminate
INFO: Close rdr --
java.io.IOException: Read error
at java.io.RandomAccessFile.read(Native Method)
at java.io.RandomAccessFile.readLine(RandomAccessFile.java:871)
at Worker.run(Worker.java:67)
at java.lang.Thread.run(Thread.java:662)
Oct 30, 2011 1:28:35 PM Worker$1 terminate
INFO: Set abort = true --
Oct 30, 2011 1:28:35 PM Worker run
INFO: Leaving run() --