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

时间:2013-05-16 13:59:28

标签: java multithreading

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

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

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

这是我的主题的一个示例。

    public void run{

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

         }catch(Exception e){
             //log
         }
    }

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

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

5 个答案:

答案 0 :(得分:10)

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

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

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

KILL QUERY id;
  

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

要知道ID,请在步骤中将第一行设为:SELECT CONNECTION_ID();。此ID可用于终止它。

答案 1 :(得分:7)

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

  

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方法将DAO调用委托给另一个线程,让它监听中断并调用cancel。

这是a post where somebody's using a Spring JdbcTemplate to cancel a query。所以它适用于那里的人(使用MySQL)。

see this answer describing how queries get canceled in Oracle

答案 2 :(得分:3)

  

仍然我得到结果事件我调用interrupt()。有没有其他方法可以做到这一点还是我做错了什么?

当您的线程被中断时,您需要检查run()您的线程是否通过isInterrupted()条件。

我认为interrupt是实现此目标的最佳方式,因为an interrupt will unblock some blocking IO和同步请求。一个定制的解决方案无法做到这一点。

答案 3 :(得分:1)

您的线程代码需要捕获InterruptedException,并在您的线程上设置中断标志。有关详细信息,请参阅this JavaSpecialist newsletter

  try {
    // ... 
  } 
  catch (InterruptedException ex) {
    Thread.currentThread().interrupt(); // very important
    break;
  }

要中断的线程不得受计算限制。也就是说,它应该执行网络IO,睡眠等,以便捕获并响应InterruptedException。诸如while(1) {}之类的循环不会被中断。

答案 4 :(得分:0)

下面的代码将中断线程无限期地运行,中断线程将被强制停止。

         @Override public void run() 
           {   // infinite loop to process

                   while(true) // your variable 
                   {                              
                      // We've been interrupted: no more processing.
                      if(Thread.currentThread().isInterrupted()){
                         return;
                       }
                   }

            }
         }