Java 如何中断使用Postgresql运行JDBC查询的线程?
我有一个线程池,运行的任务主要是使用JDBC查询Postgresql。如果取消已提交任务的未来将取消任何正在进行的查询,这将非常方便。有没有一个简单的方法可以做到这一点?它只适用于Postgresql。您可以使用: 如果DBMS和驱动程序都支持中止SQL语句,则取消此语句对象。一个线程可以使用此方法取消另一个线程正在执行的语句Java 如何中断使用Postgresql运行JDBC查询的线程?,java,multithreading,postgresql,jdbc,Java,Multithreading,Postgresql,Jdbc,我有一个线程池,运行的任务主要是使用JDBC查询Postgresql。如果取消已提交任务的未来将取消任何正在进行的查询,这将非常方便。有没有一个简单的方法可以做到这一点?它只适用于Postgresql。您可以使用: 如果DBMS和驱动程序都支持中止SQL语句,则取消此语句对象。一个线程可以使用此方法取消另一个线程正在执行的语句 cancel()在PostgreSQL JDBC驱动程序中实现。您可以使用: 如果DBMS和驱动程序都支持中止SQL语句,则取消此语句对象。一个线程可以使用此方法取消另一
cancel()
在PostgreSQL JDBC驱动程序中实现。您可以使用:
如果DBMS和驱动程序都支持中止SQL语句,则取消此语句对象。一个线程可以使用此方法取消另一个线程正在执行的语句
cancel()
是在PostgreSQL JDBC驱动程序中实现的。事实证明,Postgres JDBC连接有一个非标准的cancelQuery()方法,用于取消连接上运行的任何查询。因此,我将提交任务及其连接时返回的future包装在一起,并覆盖cancel()以调用cancelQuery()
import org.postgresql.core.BaseConnection;
私有静态类混淆实现了未来{
私人未来包装;
私有易失性连接;
公共布尔值取消(布尔值可能中断刷新){
布尔ans=wrapped.cancel(可能中断frunning);
连接con=this.con;
如果(con!=null){
试一试{
con.unwrap(BaseConnection.class).cancelQuery();
}捕获(SQLE异常){
log.error(“无法取消查询:+e”);
}
}
返回ans;
}
...
事实证明,Postgres JDBC连接有一个非标准的cancelQuery()方法,用于取消连接上运行的任何查询。因此,我将提交任务及其连接时返回的future包装在一起,并覆盖cancel()以调用cancelQuery()
import org.postgresql.core.BaseConnection;
私有静态类混淆实现了未来{
私人未来包装;
私有易失性连接;
公共布尔值取消(布尔值可能中断刷新){
布尔ans=wrapped.cancel(可能中断frunning);
连接con=this.con;
如果(con!=null){
试一试{
con.unwrap(BaseConnection.class).cancelQuery();
}捕获(SQLE异常){
log.error(“无法取消查询:+e”);
}
}
返回ans;
}
...
您的runable需要检查线程
,这样,如果您尝试取消未来,未来可以对此做出反应,并取消它正在执行的语句问题是,当线程被中断时,线程在Postgres JDBC驱动程序代码中,特别是从套接字读取时,什么也没有发生。如果该进程没有反应,您就无能为力。我相信在这种情况下,您应该能够有某种超时+回滚逻辑,这样,如果您尝试取消未来,未来可以对此做出反应,并取消它正在执行的语句问题是,当线程被中断时,线程在Postgres JDBC驱动程序代码中,特别是从套接字读取时,什么也没有发生。如果该进程没有反应,您就无能为力。我相信在这种情况下,您应该能够有某种超时+回滚逻辑。这种方法的问题是我需要访问任务正在使用的语句。这是可能的,但很混乱。这种方法的问题是我需要访问语句正在被任务使用。这是可能的,但很混乱。您最好将增强请求作为BaseConnection
接口应为驱动程序内部提交。公共扩展名在org.postgresql.PGConnection
中定义。您最好将增强请求作为BaseConnection
接口应为驱动程序提交-内部.Public扩展在org.postgresql.PGConnection
import org.postgresql.core.BaseConnection;
private static class ConFuture<T> implements Future<T> {
private Future<T> wrapped;
private volatile Connection con;
public boolean cancel(boolean mayInterruptIfRunning) {
boolean ans = wrapped.cancel(mayInterruptIfRunning);
Connection con = this.con;
if (con != null) {
try {
con.unwrap(BaseConnection.class).cancelQuery();
} catch (SQLException e) {
log.error("Unable to cancel query: " + e);
}
}
return ans;
}
...