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.
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.
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.
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.
The only way to stop a thread asynchronously is the stop() method.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With