我启动了几个线程,但是我没有通过信号或其他东西来阻止它们的引用。
例如,我不能将像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查询。
答案 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;
}
}
}
}