这个c3p0的线程是怎么回事?为什么总是等待状态,我关闭了啊

恺哥 发布于 2012/03/01 08:55
阅读 3K+
收藏 0

线程名:

com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0

每次跑完程序后,都会出现一大堆等待线程,初步怀疑数据库连接使用后没有被关闭;以下是我的代码和配置,请过来人帮着看一眼,谢谢

	@Bean(destroyMethod="close")
	public DataSource dataSource() {
		return this.getDS(Jdbc.JDBC_URL, Jdbc.JDBC_DRIVER_CLASS_NAME, Jdbc.JDBC_USER_NAME, Jdbc.JDBC_PWD);
	}

c3p0配置:

	private DataSource getDS(String url,String driver,String username,String pwd){
		try {
			ComboPooledDataSource cpds = new ComboPooledDataSource();
			cpds.setJdbcUrl(url);
			cpds.setDriverClass(driver);
			cpds.setUser(username);
			cpds.setPassword(pwd);
			
			cpds.setMinPoolSize(1);
			cpds.setMaxPoolSize(20);
			cpds.setInitialPoolSize(1);
			
			//<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
			cpds.setAcquireIncrement(1);
			//获取connnection时测试是否有效
			cpds.setTestConnectionOnCheckin(true);
			//自动测试的table名称
			cpds.setAutomaticTestTable("C3P0TestTable");
			//set to something much less than wait_timeout, prevents connections from going stale
			cpds.setIdleConnectionTestPeriod(18000);
			//set to something slightly less than wait_timeout, preventing 'stale' connections from being handed out
			cpds.setMaxIdleTime(25000);
			
			return cpds;
		} catch (PropertyVetoException e) {
			e.printStackTrace();
			return null;
		}
	}

获得数据源方法:

	@Bean(destroyMethod="close")
	public DataSource dataSource() {
		return this.getDS(Jdbc.JDBC_URL, Jdbc.JDBC_DRIVER_CLASS_NAME, Jdbc.JDBC_USER_NAME, Jdbc.JDBC_PWD);
	}
//配置bean方法
	@Bean 	public UserDao userDaoService() {
		return UserDao.getInstance(dataSource());
	}
userDao
public class UserDao {
	private static JdbcTemplate jdbcTemplate = null;
	private static DataSource ds = null;

	static class UserDaoHolder {   
	    static UserDao instance = new UserDao();   
	}
	
	public static UserDao getInstance(DataSource dataSource) {
		ds = dataSource;
		return UserDaoHolder.instance;   
	}
	
	private UserDao(){
		//初始化jdbc模板
		jdbcTemplate = new JdbcTemplate(ds);
	}
}

使用userDao
public class WzJob implements Job {
	
	private ApplicationContext ctx = null;
	private WzDao wzDao = null;
	private UserDao userDao = null;
	
	public WzJob(){
		ctx = new AnnotationConfigApplicationContext(AppConfig.class);
		wzDao = ctx.getBean(WzDao.class);
		userDao = ctx.getBean(UserDao.class);
	}
}

这种调用和配置有啥问题吗?
为啥每次执行操作后,都留了一大堆的等待线程,起初以为是httpClient使用完毕后没有关闭,后来发现是com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0
这个线程,不行的话,我不用连接池了,改用手动控制连接

望给予帮助,我这边也在调试,有什么新进展会及时分享出来,谢谢大家

 

以下是问题补充:

@恺哥:@Bean(destroyMethod="close") 这个配置到底起不起作用 以前都是用xml进行spring的配置,这次是通过annotation进行配置的 (2012/03/01 08:58)
加载中
0
乱世键客
乱世键客

你每次调用getDS都会new一个ComboPooledDataSource,这个类应该只保留一个实例即可,和线程池的使用无关。

0
恺哥
恺哥

刚刚用jvisualvm dump了thread

"com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0" daemon prio=6 tid=0x0342ac00 nid=0x2e38 in Object.wait() [0x082bf000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
	- locked <0x19db8918> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner)

   Locked ownable synchronizers:
	- None

"Timer-50" daemon prio=6 tid=0x0342a000 nid=0x4728 in Object.wait() [0x0826f000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.util.TimerThread.mainLoop(Timer.java:509)
	- locked <0x19db8550> (a java.util.TaskQueue)
	at java.util.TimerThread.run(Timer.java:462)

   Locked ownable synchronizers:
	- None

0
清凌渡
清凌渡
c3p0 不是连接池吗? 
0
恺哥
恺哥
对呀,目前怀疑连接可能没有被释放导致的,正在测试
0
Andre.Z
Andre.Z

连接池里面的连接本来就是不释放的,只是丢回了连接池里面,物理连接是不会释放的。要释放连接的话,用什么连接池啊,直接写好了。
数据库连接是TCP/IP连接,创建和关闭的开销都是比较大的,缓存了没直接物理释放难道不好???
看错误估计是其它线程在等待连接池中的可用连接。当取不到可用连接的时候,业务线程就会wait()的 - -,c3p0的log日志没有么?

0
恺哥
恺哥
关键是越积压越多,没多长时间就溢出了
0
毕成功

如果系统等待的线程比较少,可以把池配置的小一点,初始化的线程数也少一点。另外对于长时间不用的线程,在不低于最小线程数的情况下,会自动释放。

仔细研究一下配置参数就知道了

0
恺哥
恺哥
谢谢大家,我的这个服务是个定时器,就那个两三个时间段跑数据,平时都是空闲,我看我需要把连接池干掉,直接jdbc
0
demon
demon

引用来自“乱世键客”的答案

你每次调用getDS都会new一个ComboPooledDataSource,这个类应该只保留一个实例即可,和线程池的使用无关。

说得好,正解。

0
恺哥
恺哥

引用来自“demon”的答案

引用来自“乱世键客”的答案

你每次调用getDS都会new一个ComboPooledDataSource,这个类应该只保留一个实例即可,和线程池的使用无关。

说得好,正解。

可不是咋的
返回顶部
顶部