3

我正在使用c3p0來處理多線程環境中的數據庫連接池。這個問題可能涉及其他池庫,但這是我的。連接池和Thread.interrupt()

最近,我需要實現的直接或間接使用C3P0這樣的線程interrupt離子處理,並已經注意到,如果interrupt()被稱爲權當c3p0Datasource.getConnection()試圖一Connection從池中取出了我,它拋出一個InterruptedException

顯然,出現這種情況的,因爲wait()

at java.lang.Object.wait(Native Method) 
at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1414) 

酷。問題是你如何正確處理這個問題 - 兩種情況都是這樣的:a)你想在線程終止前繼續處理事務,並且b)你想中止。

我試過了一個似乎工作正常的解決方案(發佈爲答案) - 實際上,我認爲這個主題已關閉。隨意切入,否則,謝謝!

回答

3

我做了一個簡單的測試,在1秒鐘內發射了很多Connection請求,每次執行一次SELECT時tim確定池的瓶頸,然後調用interrupt()

我發現的是connection對象在抓到InterruptedException之後仍然很好,即使堆棧跟蹤顯示我在awaitAvailable(..)處出現了c3p0崩潰。在這第二秒鐘,我檢查他們的來源,當然,他們處理InterruptedException。他們甚至提出了一個適當的警告:

WARNING: [email protected] -- an attempt to checkout a resource was interrupted, and the pool is still live: some other thread must have either interrupted the Thread attempting checkout! 

告訴我們它仍然活着,儘管介於很多詞fuzz。解決了。

無論如何這裏是測試。

ComboPooledDataSource ds = new ComboPooledDataSource(); 

// testing with various pool sizes - same effect 
ds.setMinPoolSize(1); 
ds.setMaxPoolSize(5); 
ds.setInitialPoolSize(2); 

Thread connectingThread = new Thread() { 

    public void run() { 
     Connection cnxn = null; 
     while (true) { 
      try { 
       cnxn = ds.getConnection(); 
       System.out.println("Got connection.); 
       executeQuery(cnxn); 
      } catch (SQLException e) { 
       System.out.println("Got exception."); 
       e.printStackTrace(); 

       // SOLUTION: 
       Throwable cause = e.getCause(); 
       if (cause instanceof InterruptedException) { 
        System.out.println("Caught InterruptedException! Cnxn is " + cnxn); 

        // note that cnxn is a com.mchange.v2.c3p0.impl.NewProxyConnection 
        // also note that it's perfectly healthy. 
        // 
        // You may either want to: 
        // a) use the cnxn to submit your the query 

        executeQuery(cnxn); 
        cnxn.close() 

        // b) handle a proper shutdown 

        cnxn.close(); 

       } 
       break; 
      } 
     } 
    }; 
}; 

connectingThread.start(); 

try { 
    Thread.sleep(1000); 
} catch (InterruptedException e) {   e.printStackTrace();  } 

connectingThread.interrupt();