12

我启动了几个线程,但我没有他们的引用可以通过信号或其他方式停止。例如,我不能将变量传递running=false给那些线程,因为我没有它们的引用,但有它们的名称。

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

    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
         }
    }

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

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

4

5 回答 5

11

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

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

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

KILL QUERY id;

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

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

于 2013-07-23T14:29:26.503 回答
8

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

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

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

于 2013-05-16T14:11:59.883 回答
3

我仍然得到我调用中断()的结果事件。有没有其他方法可以做到这一点,或者我做错了什么?

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

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

于 2013-05-16T14:18:18.577 回答
1

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

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

要中断的线程必须不受计算限制。也就是说,它应该正在执行网络 IO、睡眠等,以便捕获和响应InterruptedException. 诸如while(1) {}不会中断的循环。

于 2013-05-16T14:03:19.983 回答
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;
                       }
                   }

            }
         }
于 2013-05-16T15:04:47.137 回答