我已经在新线程中启动了一些进程:
FutureTask<?> futureTask = new FutureTask<Void>(() -> {
startSomeProcess();
}, null);
在startSomeProcess
方法中,我为每个项目生成报告:
for (Item item : items) {
if (Thread.interrupted()) {
logger.info("currentThread isInterrupted");
return;
}
generateReport(item);
}
在generateReport()
方法中,我执行一些select to DB并从ResultSet
生成excel报告:
try (PreparedStatement ps = conn.prepareStatement(query.toString(),
ResultSet.TYPE_SCROLL_INSENSITIVE)) {
ResultSet rs = ps.executeQuery();
//and fill excel from rs
...
但我的ps.executeQuery();
可以执行很长时间(1秒999999h。
我有取消按钮。如果它按我做这个
futureTask.cancel(true);
并检查startSomeProcess();
方法中的异常。但我无法检查和中断ps.executeQuery();
。当我futureTask.cancel(true);
这个executeQuery
抛出异常时。但我不配置这个。这是自动的。
我的语言:当我中断线程时 - 我可以自己中断查询到数据库,还是刚刚发生,我只能处理错误?
编辑:
用户发送命令 - “取消报告生成”。我晕倒了futureTask并调用了cancel()
方法。并打破构建报告。但是如果ps.executeQuery();已经开始了 - 我不知道怎么打破它
答案 0 :(得分:1)
我的问题:当我中断线程时 - 我可以自己中断对数据库的查询,还是刚刚发生,我只能处理错误?
中断线程只在线程上设置一个标志,这只会导致抛出InterruptedException
的那些方法。在这种情况下,SQL方法不会抛出InterruptedException
,因此只调用future.cancel(true)
将不起作用。
如果您尝试取消正在运行的SQL查询,那么您需要canceling the underlying Statement
在JDBC级别进行此操作。引用Statement.cancel()
的javadoc:
如果DBMS和驱动程序都支持中止SQL语句,则取消此Statement对象。一个线程可以使用此方法来取消正由另一个线程执行的语句。
所以在你的情况下,这意味着另一个线程将不得不取消你的ps
。我创建了一个包装generateReport()
方法的对象,该方法将PreparedStatement ps
放入volatile
字段。然后,当方法执行ps
时,它会从字段执行,而另一个线程可以调用cancel()
上调用ps.cancel()
的对象。
请务必注意,查询取消是SQL数据库和JDBC驱动程序相关的。并非所有数据库都支持它。
答案 1 :(得分:0)