Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping a non-looping Java thread

This may be a case of me just misunderstanding what I've read, but all the examples for killing a thread in Java seem to indicate that you have to signal a thread to kill itself; you can't kill it from the outside without some serious risks. The problem is, all the examples of how to "politely" ask a thread to die have some kind of looping so all you have to do is watch a flag on every iteration.

So, what I've got is a thread that does something that just takes a while (a series of SQL queries). It's certainly possible for me to just have a check after each step, but they aren't in a loop and there isn't a very elegant way that I'm aware of to get around that. Here's an example of what I'm doing:

new Thread(new Runnable(){
    public void run(){
        //query 1
        Connection conn = db.getConnection();
        Statement s = conn.createStatement();
        ResultSet rs = s.executeQuery("SELECT ...");
        while(rs.next()){
            //do stuff
        }

        //query 2
        rs = s.executeQuery("SELECT ...");
        while(rs.next()){
            //do stuff
        }

        //query 3
        rs = s.executeQuery("SELECT ...");
        while(rs.next()){
            //do stuff
        }
    }
}).start();

This is an example, I don't use anonymous inner classes but it illustrates that my run() method can't elegantly stop itself. Futhermore, even I check after each step, if a particular query takes a very long time to run, this code would not be able to stop until after the query was complete.

This code is for a GUI application, and I would really like to find a good way to kill a thread quickly without using Thread.stop().

EDIT - yshavit's answer was a big help, as I wasn't aware that Statement.cancel() existed. If you're curious, the answer to my particular problem was to build out a more abstracted database access class. The class had to create a child thread to execute the query and loop while it was running, checking on every iteration if the current thread (not the child) was interrupted. If it does get interrupted, it just calls Statement.cancel() and the child thread will throw an exception and die. Not all JDBC drivers support Statement.cancel(), but Oracle 11g does.

like image 229
monitorjbl Avatar asked Feb 29 '12 02:02

monitorjbl


People also ask

How do you stop a thread in Java?

Modern ways to suspend/stop a thread are by using a boolean flag and Thread. interrupt() method. Using a boolean flag: We can define a boolean variable which is used for stopping/killing threads say 'exit'. Whenever we want to stop a thread, the 'exit' variable will be set to true.

How do you stop a thread from looping in Java?

1 - Since Thread. stop() is deprecated, I can implement a stopThisThread() method that uses a n atomic check-condition variable. 2 - Send a Death Event object or something like that to the queue. When the thread fetches a death event, it exits.

How do I force a thread to stop?

To end the thread before going through the current loop you can use the break keyword. This avoids using deprecated methods such as Thread. stop() . The thread will finish the current task and then stop itself naturally.

How do you stop an infinite thread in Java?

The only way to stop a thread asynchronously is the stop() method.


1 Answers

Find out what takes a while, and cancel it. If the thing that takes the most time are the rs.next() loops, you can do:

while(rs.next()){
    if (myVolatileBooleanSaysToStop) {
        return; // or whatever
    }
    //do stuff
}

If the thing that takes a while are the statements, and your JDBC driver/server support Statement.cancel, then you can publish your Statement to a second thread which is responsible for calling Statement.cancel as appropriate. I'm not sure, but I think that'll result in a SQLException from the driver, which you can then somehow identify as having come from the cancellation, and handle accordingly.

Also, you should consider refactoring a bit. You have three chunks of "run a query, iterate over its results" that could be factored into a method (which would then take care of closing the statement, etc).

like image 187
yshavit Avatar answered Oct 03 '22 23:10

yshavit