Connection Pool and Thread.interrupt ()

I am using c3p0 to handle database connection pooling in a multithreaded environment. The question may refer to other pools of libs, but this is what I have.

Lately I needed to implement interrupt ion handling on such threads using c3p0 directly or indirectly and noticed that if interrupt()

called correctly when c3p0Datasource.getConnection()

trying to get from <pool Connection

, it throws InterruptedException

.

Obviously, this is due to wait()

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

      

Cool. The question is how do you handle this correctly - both are the case a) you want to continue the transaction before your thread finishes, and b) you want to abort.

I've tried a solution that seems to work fine (posted as an answer) - in fact, I think this question is closed. Feel free to chip otherwise, thanks!

+3


source to share


1 answer


I did a simple test, firing a lot of queries Connection

for 1 second, doing a SELECT every tim time, make sure the bottlenecks are in the pool, and then calls interrupt()

.

What I found was that the object is Connection

fine and dandy after capture InterruptedException

, although the stacktrace shows me meltdown's c3p0 awaitAvailable(..)

. At this very moment, I am checking their sources, and of course they are processing InterruptedException

. They even throw the correct warning:

WARNING: com.mchange.v2.resourcepool.BasicResourcePool@5bcf4b61 -- 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!

      



informing us that he is still alive, although there are many words between them. Solved.

Here's a test anyway.

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

      

+3


source







All Articles