我的需求与这个非常相似,只是我长时间运行的 IO 操作是数据库选择。
该线程中提出了一个相当有创意的解决方案,涉及在单独的线程中关闭 IO 流。但是,我并没有真正引用输入流或套接字。
当我使用 spring-jdbc 时,我什至无法关闭正在使用的连接,它不能让我访问正在使用的底层连接。我相信JdbcTemplate.getDataSource().getConnection()
可能会从数据源返回另一个连接。
感谢我能得到的任何帮助/建议。
使用JdbcTemplate.execute(PreparedStatementCreator, PreparedStatementCallback)
在 PreparedStatementCreator 中,您可以访问 Statement,您可以将其提供给另一个线程。这个其他线程创建一个计时器,并在必要时在 Statement 上调用 .cancel。
正如 Istvan 提到的,PreparedStatementCreator 是要走的路。粘贴我的实现以防万一它有帮助..
private final long timeout = 1000; //timeout in seconds
final SqlRowSet rowSet = jdbcTemplate.getJdbcOperations().query(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
if (timeout>0){
Timer timer = new Timer();
timer.schedule(new ConnectionInterrupter(con), timeout*1000);
}
return con.prepareStatement(queryString);
}
}, new ResultSetExtractor<SqlRowSet>() {
@Override
public SqlRowSet extractData(ResultSet rs) throws SQLException, DataAccessException {
CachedRowSet rowSet = newCachedRowSet();
rowSet.populate(rs);
return new ResultSetWrappingSqlRowSet(rowSet);
}
protected CachedRowSet newCachedRowSet() throws SQLException {
return new CachedRowSetImpl();
}
});
private class ConnectionInterrupter extends TimerTask {
private final Connection connection;
public ConnectionInterrupter(Connection connection) {
this.connection = connection;
}
@Override
public void run() {
try {
logger.warn("Connection timeout has occurred. Manually closing the connection ...");
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}