My program analyzes a large number of documents and occasionally gets a page that causes an infinite or very long loop. This is not analyzable in advance. I want to kill the particular page and continue with the next one (throwing away any results for the offending page). I have read SO answers such as this How to stop execution after a certain time in Java? and have written the following code:
// main program
private void runThread() throws InterruptedException {
long timeout = 15000L;
RunPageAnalyzer runPageAnalyzer = new RunPageAnalyzer(this);
Thread t = new Thread(runPageAnalyzer);
long startTime = System.currentTimeMillis();
t.start();
while (t.isAlive()) {
t.join(1000);
long delta = System.currentTimeMillis() - startTime;
LOG.debug("delta: "+delta);
if (delta > timeout && t.isAlive()) {
t.interrupt();
t.join;
break;
}
}
}
the method in the same class called by the thread
void runActions() {
// variable length calculation which should be abandoned if too long
}
and the Runnable:
class RunPageAnalyzer implements Runnable {
private PageAnalyzerAction pageAnalyzerAction;
public RunPageAnalyzer(PageAnalyzerAction pageAnalyzerAction) {
this.pageAnalyzerAction = pageAnalyzerAction;
}
public void run() {
try {
pageAnalyzerAction.runActions();
} catch (Exception e) {
LOG.debug("Exception running thread ", e);
}
}
The output for a normal termination of runActions() seems OK:
=========== page 1 =============
13863 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - pageActions: 24 on page 0
14863 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 1000
15864 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 2001
16864 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 3001
16975 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 3112
16975 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - finished page
but when the time limit is exceeded the process hangs in t.join()
.
=========== page 2 =============
16975 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - pageActions: 24 on page 0
17976 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 1001
18976 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 2001
// ...
30976 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 14001
31976 [main] DEBUG org.xmlcml.graphics.control.page.PageAnalyzerAction - delta: 15001
If I omit the t.join()
then the process behaves as I would expect but I am worried that this might simply be building up huge numbers of threads that will be a problem later.
UPDATE:
The answers so far have suggested that this is non-trivial (and I didn't find the standard Java examples/tutorials very helpful). The key point is that runActions()
has to know explicitly that it might be interrupted. join()
is not the primary problem because the threads just keep going.
FURTHER QUESTION:
Do I have to insert Thread.currentThread().isInterrupted()
in all the places in runActions()
which I expect to be in unpredictably long loops?