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