小编典典

停止非循环Java线程

sql

这可能是我误读了我所读内容的一种情况,但是在Java中杀死线程的所有示例似乎都表明您必须发出信号以杀死自己。您不能在没有严重风险的情况下从外面杀死它。问题是,所有有关如何“礼貌地”要求线程死亡的示例都有某种循环,因此您要做的就是观察每次迭代中的标志。

因此,我得到的是一个线程,该线程执行的操作仅需要一段时间(一系列SQL查询)。我当然可以在每个步骤之后进行检查,但是它们并没有处于循环中,并且我没有一种非常优雅的方式可以解决此问题。这是我正在做的事的一个例子:

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();

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

这段代码是针对GUI应用程序的,我真的很想找到一种无需使用Thread.stop()即可快速杀死线程的好方法。

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


阅读 220

收藏
2021-04-17

共1个答案

小编典典

找出需要一些时间的情况,然后将其取消。如果最耗时的事情是rs.next()循环,则可以执行以下操作:

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

如果需要花费一些时间的是语句以及JDBC驱动程序/服务器支持Statement.cancel,那么您可以将您的内容发布Statement到第二个线程,该线程负责进行Statement.cancel适当的调用。我不确定,但是我认为这会导致SQLException驱动程序产生a
,然后您可以以某种方式将其标识为来自取消,并进行相应处理。

另外,您应该考虑重构。您可以将三个“运行查询,遍历其结果”的块放入一个方法中(然后将处理关闭该语句等)。

2021-04-17