3

Я использую c3p0 для обработки пула соединений с базой данных в многопоточной среде. Вопрос может относиться к другим пулам библиотек, но это то, что у меня есть.Пул соединений и Thread.interrupt()

Недавно я необходимо реализовать interrupt обработку ионов на таких потоках с использованием прямо или косвенно c3p0, и заметил, что если interrupt() называется правильно, когда c3p0Datasource.getConnection() пытается принести мне Connection из бассейна, он бросает InterruptedException.

Очевидно, что это происходит из-за wait()

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

Круто. Вопрос в том, как вы справляетесь с этим правильно - и то, и другое: а) вы хотите продолжить транзакцию до того, как ваш поток завершится, и b) вы хотите прервать.

Я пробовал решение, которое, кажется, работает нормально (опубликовано как ответ) - на самом деле, я думаю, этот вопрос закрыт. Не стесняйтесь чип в противном случае, спасибо!

ответ

3

Я сделал простой тест, выпустив много запросов Connection в течение 1 секунды, выполняя SELECT каждый раз, чтобы убедиться, что узкие места в пуле, а затем вызывает interrupt().

То, что я обнаружил, что connection объект хорошо и денди после InterruptedException поимки, даже несмотря на то, StackTrace показывает мне C3P0 расплавление в awaitAvailable(..). На этой самой секунде я проверяю их источники, и, конечно же, они обрабатывают 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! 

говорит нам, что это до сих пор живут, хотя между ними много слов пуха. Решаемые.

В любом случае, это тест.

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();