有时当我在第三方专用JDBC驱动程序上调用connect()时,它永远不会返回,并且堆栈跟踪显示它等待套接字读取(通常)。是否存在从另一个线程强制取消此操作的通用方法?这是一个阻塞的I / O调用,所以Thread.interrupt()不起作用,我不能直接关闭套接字,因为我没有访问它,因为它是在专有代码中创建的。
我正在寻找通用解决方案,因为我有一个异构的数据库环境(Oracle,MySQL,Sybase等)。但也欢迎特定于驾驶员的建议。谢谢,
答案 0 :(得分:2)
啊......使用闭源库的乐趣......
如果interrupt()
不起作用,并且您无法设置某种超时,那么我认为没有安全的方法可以做到这一点。调用Thread.kill()
可能会完成这项工作,但该方法已被弃用,因为它非常不安全。这就是Thread.kill()
的不安全感可以回来咬你的那种场景。
我建议您只是编写应用程序代码以放弃卡住的线程。假设您的应用程序没有反复尝试连接到数据库,那么卡住的线程并不是一个巨大的开销。
或者使用更好的JDBC驱动程序。 (在出门的路上,向供应商抱怨他们的司机太不灵活了。有人可能会听你的话......)
答案 1 :(得分:2)
没有标准的JDBC接口来设置连接或读取超时,因此如果JDBC驱动程序支持超时,则必然会使用专有扩展。对于Oracle JDBC瘦驱动程序,您可以例如设置系统属性“oracle.net.CONNECT_TIMEOUT”和/或“oracle.jdbc.ReadTimeout”,或者将Properties实例传递给DriverManager.getConnection并设置这些属性。虽然没有特别详细记录,但Oracle特定属性列在API documentation。
中对于其他JDBC驱动程序,文档应包含相关参考。
答案 2 :(得分:1)
如果运行此连接尝试的线程被中断,则至少有一个JDBC驱动程序(不是您列出的那个)将干净地关闭连接。我不知道这是否适用于所有司机。
答案 3 :(得分:0)
这是Java的问题,而不是JDBC驱动程序。在某些情况下,套接字连接调用会忽略超时参数,并且可能需要几分钟才能返回。当防火墙阻止端口时,我们就会发生这种情况它发生在所有TCP连接(HTTP,RMI)上。
我找到的唯一解决方案是在不同的线程中打开连接,
private static final ExecutorService THREADPOOL
= Executors.newCachedThreadPool();
private static <T> T call(Callable<T> c, long timeout, TimeUnit timeUnit)
throws InterruptedException, ExecutionException, TimeoutException
{
FutureTask<T> t = new FutureTask<T>(c);
THREADPOOL.execute(t);
return t.get(timeout, timeUnit);
}
try {
Data data = call(new Callable<Data>() {
public Data call() throws Exception
{
// Open connection, get data here
return data;
}, 2, TimeUnit.SECONDS);
} catch (TimeoutException e) {
System.err.println("Data call timed-out");
}