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!
source to share
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();
source to share