中断/取消卡住的连接()呼叫

时间:2009-11-09 22:53:13

标签: java jdbc sockets

有时当我在第三方专用JDBC驱动程序上调用connect()时,它永远不会返回,并且堆栈跟踪显示它等待套接字读取(通常)。是否存在从另一个线程强制取消此操作的通用方法?这是一个阻塞的I / O调用,所以Thread.interrupt()不起作用,我不能直接关闭套接字,因为我没有访问它,因为它是在专有代码中创建的。

我正在寻找通用解决方案,因为我有一个异构的数据库环境(Oracle,MySQL,Sybase等)。但也欢迎特定于驾驶员的建议。谢谢,

4 个答案:

答案 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");
   }