2009-11-09 39 views
4

有時,當我在第三方專有JDBC驅動程序上調用connect()時,它永遠不會返回,並且堆棧跟蹤顯示卡住等待套接字讀取(通常)。有沒有一種通用的方法來從另一個線程強制取消這個操作?這是一個阻塞的I/O調用,所以Thread.interrupt()將不起作用,並且我無法直接關閉套接字,因爲我無法訪問它,因爲它是在專用代碼中創建的。中斷/取消卡住的connect()調用

我在尋找通用解決方案,因爲我有一個異構的數據庫環境(Oracle,MySQL,Sybase等)。但司機的具體建議也是受歡迎的。謝謝,

回答

2

沒有標準的JDBC接口來設置連接或讀超時,所以如果JDBC驅動程序完全支持超時,那麼您必然會使用專有擴展。對於Oracle JDBC瘦驅動程序,您可以設置系統屬性「oracle.net.CONNECT_TIMEOUT」或者「oracle.jdbc.ReadTimeout」,或者將一個Properties實例傳遞給DriverManager.getConnection並設置這些屬性。雖然沒有特別詳細記錄,但Oracle特定屬性列在API documentation中。

對於其他JDBC驅動程序,文檔應包含相關參考。

1

至少有一個JDBC驅動程序(不是您列出的那個驅動程序)將乾淨地關閉連接,如果此連接嘗試運行的線程中斷。我不知道這是否會適用於所有司機。

2

啊......使用封閉源代碼庫的樂趣...

如果interrupt()不工作,你不能設置一些超時,那麼我認爲是沒有安全的方式來做到這一點。打電話Thread.kill()可能做這項工作,但該方法已被棄用,因爲它是非常不安全的。而這種情況下Thread.kill()的不安全性可能會回來並咬你。

我建議你簡單地編寫你的應用程序來放棄卡住的線程。假設您的應用程序不會反覆嘗試連接到數據庫,卡住的線程並不是很大的開銷。

或者使用更好的JDBC驅動程序。 (並且在出門的時候,向供應商抱怨他們的驅動程序太不靈活了,有人可能會聽你的...)

+0

這是一個選項,我已經打了,但它實際上相當於同樣的事情,放棄線程,因爲使用Thread.stop ()不影響阻塞I/O操作。 – Dan 2009-11-10 16:01:54

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"); 
    } 
+0

我會嘗試。我不能放棄主線程,因爲它位於servlet容器的託管池中,但這應該起作用。 – Dan 2009-11-10 16:04:41