连接池和 Thread.interrupt()

问题描述 投票:0回答:1

我正在使用 c3p0 来处理多线程环境中的数据库连接池。这个问题可能与其他池库有关,但这就是我所拥有的。

最近我需要直接或间接使用 c3p0 在此类线程上实现 interruption 处理,并且注意到如果在

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) 你想中止。

我尝试了一个似乎工作正常的解决方案(作为答案发布)——实际上,我认为这个主题已经结束。否则请随意补充,谢谢!

java connection-pooling c3p0 interrupt-handling interrupted-exception
1个回答
3
投票

我做了一个简单的测试,在 1 秒内发出大量

Connection
请求,每次执行 SELECT 确保池瓶颈,然后调用
interrupt()
.

我发现

connection
对象在
InterruptedException
被捕获后很好而且花花公子,即使堆栈跟踪显示我在
awaitAvailable(..)
处 c3p0 崩溃。就在这一刻,我正在查看他们的消息来源,他们肯定会处理
InterruptedException
。他们甚至发出适当的警告:

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!

告诉我们它仍然存在,尽管中间有很多词模糊。解决了。

无论如何,这是测试。

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();
    
© www.soinside.com 2019 - 2024. All rights reserved.