另类解决c3p0连接池获取连接时候长时间阻塞线程问题

一直维护着旧游戏服务器 java写的,一台服务器还有3,4千人在线,看来老外还蛮怀旧的。

服务器出现无法登录时候,在服务器JDB 记录下多线程调用堆栈记录 以下是出现次数最多堆栈

[1] com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource (BasicResourcePool.java:201)
[2] com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection (C3P0PooledConnectionPool.java:232)
[3] com.mchange.v2.c3p0.PoolBackedDataSource.getConnection (PoolBackedDataSource.java:94)
[4] com.mchange.v2.c3p0.ComboPooledDataSource.getConnection (ComboPooledDataSource.java:521)
[5] org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection (LocalDataSourceConnectionProvider.java:82)
[6] org.hibernate.jdbc.ConnectionManager.openConnection (ConnectionManager.java:417)
[7] org.hibernate.jdbc.ConnectionManager.getConnection (ConnectionManager.java:144)
[8] org.hibernate.jdbc.JDBCContext.connection (JDBCContext.java:119)
[9] org.hibernate.transaction.JDBCTransaction.begin (JDBCTransaction.java:57)
[10] org.hibernate.impl.SessionImpl.beginTransaction (SessionImpl.java:1,326)
[11] org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin (HibernateTransactionManager.java:558)
[12] org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction (AbstractPlatformTransactionManager.java:374)
[13] org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary (TransactionAspectSupport.java:263)
[14] org.springframework.transaction.interceptor.TransactionInterceptor.invoke (TransactionInterceptor.java:101)
[15] org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:171)
[16] org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept (Cglib2AopProxy.java:635)

看堆栈调用线程多阻塞在获取数据库连接时候,我查过数据配置连接池100-500 ,运行线程数量也没那么多,线程池里面数据库连接应该 没有用光的

查看了[1] com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource (BasicResourcePool.java:201)行代码其实是同步函数 .

网上对synchronized 解析如下

当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块

网上搜索下类似问题,可以改成用jdbc来操作DB,效率也高,不过我不想改动太多代码,毕竟是老项目,改太多会造成不稳定

所以我想可不可以这样。减少对连接池的getConnection 调用,这样减少c3p0的线程阻塞,按照这样思路我把频繁调用保存DB的代码改成批量保存。

单独开个线程缓存对象列表 ,然后批量保存,代码如下,

@Override
public void saveListTransingTrade(final List<TransingTrade> listpo) {
// TODO Auto-generated method stub
hibernateTemplate.execute(new HibernateCallback() {

@Override
public Object doInHibernate(Session arg0) throws HibernateException,
SQLException {
// TODO Auto-generated method stub
long start=System.currentTimeMillis();
int count = 0;
for(TransingTrade t:listpo)
{
hibernateTemplate.saveOrUpdate(t);

if(count > 0&& count%SovtConfig.getInstance().getBatchsavecount() == 0)
{
arg0.flush();
arg0.clear();
}
count++;
}
arg0.flush();
arg0.clear();

log.error("batch save TransingTrade:" + listpo.size() + ",cost:"+(System.currentTimeMillis()-start));

return null;
}
});
}

改动经过测试后,放在公网运行后,发现即使在线人数3,4千人时候,也有不少空闲线程.登录游戏响应有明显提升

至于改动后性能测试,大家可以自己测试咯。主要是分享解决思路。

转载于:https://www.cnblogs.com/maikkk/p/6591608.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值