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

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

我正在使用ThreadGroup ,我总是引用它。 所以我可以这样做。 似乎它不起作用。

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

这是我的post的一个例子。

  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查询。

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

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

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

 KILL QUERY id; 

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

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

如果您的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。

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

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

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

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

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

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

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

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

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

  @Override public void run() { // infinite loop to process while(true) // your variable { // We've been interrupted: no more processing. if(Thread.currentThread().isInterrupted()){ return; } } } }