Java - 停止访问数据库的长时间运行的线程

sur*_*a2k 11 java multithreading

我启动了几个线程,但我没有通过信号或其他东西来阻止它们.例如,我不能将变量传递running=false给那些线程,因为我没有它们的引用,但是有它们的名字.

我正在使用a ThreadGroup并且我总是参考它.所以我可以做这样的事情.似乎它不起作用.

    Thread[] threads = new Thread[threadGroup.activeCount()];
    int count = threadGroup.enumerate(threads);
    for(int i = 0; i < count; i++){
        threads[i].interrupt();
    }
Run Code Online (Sandbox Code Playgroud)

这是我的帖子的一个例子.

    public void run{

         try{
             //myDAO.getRecords();
             //this takes 30seconds to 60
             //returns about 3 millions of records

         }catch(Exception e){
             //log
         }
    }
Run Code Online (Sandbox Code Playgroud)

当这个线程正在执行时,我想在中间停止它.无论如何batabase查询正在运行,但我想停止获取结果.

即使我打电话,我仍然得到了结果interrupt().有没有其他方法可以做到这一点还是我做错了什么?最终任务是取消Java中长时间运行的SQL查询.

Jat*_*tin 10

调用interrupt一个等待查询输出的线程没有任何影响,因为大多数JDBC驱动程序都不受状态影响.它仍然会被阻止,查询将继续执行.

调用cancel将终止连接和执行数据库中查询的线程.偶尔也可以,但它也会杀死连接.这可能会造成严重问题,很快就会成为瓶颈.

另一种工作解决方案是获取ID执行过程/查询的线程(在数据库端)并调用:

KILL QUERY id;
Run Code Online (Sandbox Code Playgroud)

KILL QUERY终止连接当前正在执行的语句,但保持连接本身不变.

要知道ID,请在程序中将第一行作为:SELECT CONNECTION_ID();.此Id可用于终止它.

  • 请注意,所描述的查询终止方法是 MySQL 特定的。这是Oracle技巧:http://stackoverflow.com/questions/466963/is-it-possible-to-kill-a-single-query-in-oracle-without-killing-the-session (2认同)

Nat*_*hes 7

如果您的DAO正在使用JDBC并且您想要停止正在进行的查询,那么您可以cancel在Statement上调用另一个线程:

void cancel()抛出SQLException

Cancels this Statement object if both the DBMS and driver support aborting 
an SQL statement. This method can be used by one thread to
cancel a statement that is being executed by another thread.

Throws:
    SQLException - if a database access error occurs or this method is 
    called on a closed Statement 
    SQLFeatureNotSupportedException - if the JDBC driver does not support
    this method
Run Code Online (Sandbox Code Playgroud)

您可能让run方法将DAO调用委托给另一个线程,并让它监听中断并调用cancel.

这是一个帖子,有人使用Spring JdbcTemplate来取消查询.所以它适用于那里的人(使用MySQL).

请参阅此答案,描述如何在Oracle中取消查询.