Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

killing an infinite loop in java

I am using a third-party library to process a large number of data sets. The process very occasionally goes into an infinite loop (or is blocked - don't know why and can't get into the code). I'd like to kill this after a set time and continue to the next case. A simple example is:

for (Object data : dataList) {
    Object result = TheirLibrary.processData(data);
    store(result);
}

processData normally takes 1 second max. I'd like to set a timer which kills processData() after , say, 10 seconds

EDIT I would appreciate a code snippet (I am not practiced in using Threads). The Executor approach looks useful but I don't quite know how to start. Also the pseudocode for the more conventional approach is too general for me to code.

@Steven Schlansker - suggests that unless the thirdparty app anticipates the interrupt it won't work. Again detail and examples would be appreciated

EDIT I got the precise solution I was wanting from my colleagues Sam Adams, which I am appending as an answer. It has more detail than the other answers, but I will give them both a vote. I'll mark Sam's as the approved answer

like image 368
peter.murray.rust Avatar asked Aug 15 '10 22:08

peter.murray.rust


People also ask

How do you stop an infinite loop in Java?

break is used to break or terminate a loop whenever we want. Just type break; after the statement after which you want to break the loop.

How do you break infinite loop?

Like all loops, infinite loops can be exited prematurely using the break and exit statements, and a single loop iteration can be cut short by using the continue statement, which jumps to the next loop iteration.

How do I stop a while loop running infinitely?

You can stop an infinite loop with CTRL + C . You can generate an infinite loop intentionally with while True . The break statement can be used to stop a while loop immediately.

How do you stop a running loop in Java?

Break: The break statement in java is used to terminate from the loop immediately. When a break statement is encountered inside a loop, the loop iteration stops there, and control returns from the loop immediately to the first statement after the loop.


3 Answers

One of the ExecutorService.invokeAll(...) methods takes a timeout argument. Create a single Callable that calls the library, and wrap it in a List as an argument to that method. The Future returned indicate how it went.

(Note: untested by me)

like image 175
Thorbjørn Ravn Andersen Avatar answered Nov 15 '22 05:11

Thorbjørn Ravn Andersen


Put the call to the library in another thread and kill this thread after a timeout. That way you could also proces multiple objects at the same time if they are not dependant to each other.


EDIT: Democode request

This is pseudo code so you have to improve and extend it. Also error checking weather a call was succesful or not will be of help.

for (Object data : dataList) {
    Thread t = new LibThread(data);
    // store the thread somewhere with an id
    // tid and starting time tstart 
    // threads
    t.start();
    }

while(!all threads finished)
{
    for (Thread t : threads)
    {
        // get start time of thread
        // and check the timeout
        if (runtime > timeout)
        {
            t.stop();
        }
    }
}

class LibThread extends Thread {
    Object data;

    public TextThread(Object data) 
    {
        this.data = data;
    }

    public void processData() 
    {
        Object result = TheirLibrary.processData(data);
        store(result);
    }
}
like image 21
schoetbi Avatar answered Nov 15 '22 05:11

schoetbi


Sam Adams sent me the following answer, which is my accepted one

Thread thread = new Thread(myRunnableCode);
thread.start();
thread.join(timeoutMs);
if (thread.isAlive()) {
  thread.interrupt();
}

and myRunnableCode regularly checks Thread.isInterrupted(), and exits cleanly if this returns true.

Alternatively you can do:

Thread thread = new Thread(myRunnableCode);
thread.start();
thread.join(timeoutMs);
if (thread.isAlive()) {
  thread.stop();
}

But this method has been deprecated since it is DANGEROUS.

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#stop() "This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior."

I've implemented the second and it does what I want at present.

like image 32
peter.murray.rust Avatar answered Nov 15 '22 04:11

peter.murray.rust