停止非循环Java线程 [英] Stopping a non-looping Java thread

查看:154
本文介绍了停止非循环Java线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是我误解了我所读到的内容的一种情况,但是用Java杀死一个线程的所有示例似乎表明你必须发出一个线程来自杀;没有一些严重的风险,你不能从外面杀死它。问题是,所有关于如何礼貌地要求线程死亡的例子都有某种循环,所以你要做的只是在每次迭代时都看一个标志。



<那么,我得到的是一个线程,它只需要一段时间(一系列SQL查询)。我当然可以在每一步之后进行检查,但它们不是在一个循环中,并且我没有一种非常优雅的方式可以解决这个问题。这是我正在做的一个例子:

  new Thread(new Runnable(){
public void run( ){
//查询1
连接conn = db.getConnection();
语句s = conn.createStatement();
ResultSet rs = s.executeQuery(SELECT。 ..);
while(rs.next()){
// do stuff
}

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

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

这是一个例子,我不使用匿名内部类但它说明了我的run()方法不能优雅地阻止自己。此外,即使我在每个步骤之后检查,如果特定查询需要很长时间才能运行,则此代码将无法在查询完成之后停止。



此代码适用于GUI应用程序,我真的想找到一种在不使用Thread.stop()的情况下快速终止线程的好方法。



编辑 - yshavit的答案是一个很大的帮助,因为我不知道 Statement.cancel()存在。如果你很好奇,我的特定问题的答案是构建一个更抽象的数据库访问类。该类必须创建一个子线程来执行查询并在其运行时循环,检查每次迭代是否当前线程(而不是子线程)被中断。如果它确实被中断,它只调用Statement.cancel()并且子线程将抛出异常并死掉。并非所有JDBC驱动程序都支持 Statement.cancel(),但Oracle 11g支持。

解决方案

找出需要一段时间的内容,然后取消它。如果花费最多时间的是 rs.next()循环,你可以这样做:

  while(rs.next()){
if(myVolatileBooleanSaysToStop){
return; //或者其他
}
//做东西
}

如果需要一段时间的事情是语句,并且您的JDBC驱动程序/服务器支持 Statement.cancel ,那么您可以发布语句到第二个线程,负责根据需要调用 Statement.cancel 。我不确定,但我认为这将导致来自驱动程序的 SQLException ,然后您可以以某种方式识别出来自取消,并相应地处理。



另外,你应该考虑重构一下。你有三个运行一个查询,迭代它的结果的块,可以将它们考虑在一个方法中(然后用它来关闭语句等)。


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.

解决方案

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).

这篇关于停止非循环Java线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆