返回信息流正在学习搭建1个简单好用的DAO结构,
用了spring jdbc + c3p0连接数据库mysql,
code如下:
public class ThreadRunner implements Runnable{
@Override
public void run(){
try{
DataSource ds = baseDao.getDatasource();
Connection conn = baseDao.getDatasource().getConnection();
PooledDataSource pds = (PooledDataSource) ds;
List<UserEntity> list = baseDao.getQueryBySql("select handle from UPM_USER");
for(UserEntity entity:list){
System.out.println("*****************************");
System.out.println("当前线程为:" + Thread.currentThread().getName() + "count:" + count.addAndGet(1));
// System.out.println(handle);
System.out.println(entity.getHandle());
System.out.println("connection:" + conn.hashCode());
System.out.println("空闲的连接: " + pds.getNumIdleConnectionsDefaultUser());
System.out.println("使用中的连接: " + pds.getNumBusyConnectionsDefaultUser());
if(count.intValue() == 9){
System.out.println(count);
}
}
}catch (Exception e){
e.printStackTrace();
System.out.println(e.toString());
}
}
}
调用和创建新thread的code如下:
@Test
public void getQueryList(){
for (int i=0; i<10; i++){
System.out.println(i);
new Thread(thR).start();
}
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
但是结果非常奇怪,出现了15个数据库连接
这是一条镜像帖。来源:北邮人论坛 / java / #55172同步于 2017/2/24
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
10个并发线程产生15个数据库连接的不明状况,求分析原因和改善
echojessicaa
2017/2/24镜像同步12 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
结果输出如下:
*****************************
当前线程为:Thread-2count:1
cas1
connection:1152504480
空闲的连接: 0
使用中的连接: 5
*****************************
当前线程为:Thread-9count:2
cas1
connection:808853315
空闲的连接: 0
使用中的连接: 6
*****************************
当前线程为:Thread-8count:3
cas1
connection:977347968
空闲的连接: 0
使用中的连接: 8
*****************************
当前线程为:Thread-11count:4
cas1
connection:234596579
空闲的连接: 0
使用中的连接: 10
*****************************
当前线程为:Thread-3count:5
cas1
connection:1701105699
空闲的连接: 0
使用中的连接: 12
*****************************
当前线程为:Thread-4count:6
cas1
connection:1453195003
空闲的连接: 0
使用中的连接: 14
*****************************
当前线程为:Thread-10count:7
cas1
connection:1503938704
空闲的连接: 0
*****************************
当前线程为:Thread-5count:8
cas1
使用中的连接: 11
*****************************
当前线程为:Thread-6count:9
cas1
connection:2135417684
空闲的连接: 5
使用中的连接: 10
connection:2142116456
空闲的连接: 5
*****************************
使用中的连接: 10
9
当前线程为:Thread-7count:10
cas1
connection:1218306324
空闲的连接: 5
使用中的连接: 10
并发线程的debug并不成功,跳进断点的同时其他thread就都跑完了。。。但是在数据库中查询会发现,的确存在和log相同的连接数:
运行结束后再查询数据库连接,那15个连接就不见了,说明并不是遗存连接
这个诡异的现象应该怎么查找原因呢~
你的连接池配置是不是没有指定保持最大连接数?默认是15(maxPoolSize参数)
btw楼主你知道你写的程序什么意思么?开10个线程遍历一张只有一条数据的表。。没发现打出来的日志都是颠三倒四的么?
连接池工作得很正常,没毛病
1.的确没有指定保持最大连接数,指定的话是不是每个线程都打印出15个connection了,但是这个和我想知道的是2码事唉。。。
程序运行前,connection idle+busy =0
运行时,10个线程分别调用同1个datasource查询10次,产生10+个连接(每次打印出来的连接数不一样)
我的疑问是,为啥不是产生10个连接而是多于10个。。
2.我写的这只是个test程序,遍历1个数据的表和日志颠三倒四有啥因果关系么。。难道并行的线程不就是颠三倒四的运行嘛。。。
这个test程序的现阶段目的,是希望DAO并发线程比较高的时候,能够依次处理,而不是丢连接或者connection数超出或者直接死掉
但是for循环还没设置成50或者100的时候,只是设置成10,connection数不等于10,是不是哪不太对呢~
【 在 ml3615556 的大作中提到: 】
: 你的连接池配置是不是没有指定保持最大连接数?默认是15(maxPoolSize参数)
: btw楼主你知道你写的程序什么意思么?开10个线程遍历一张只有一条数据的表。。没发现打出来的日志都是颠三倒四的么?
: 连接池工作得很正常,没毛病
自问自答,datasource中有个参数是每次创建connection个数,默认值是3,我改成1之后,10个线程就是创建10个connection了
产生多于十个连接可能是连接池自己初始化了多于10个,你设置不允许连接池有空闲conn试试?
至于为什么每次打出来连接池个数不一样,我猜,是因为连接池是默认lazy-init的,你一边用连接它一边给你初始化连接,要证实这个说法,你可以在sleep后面再开10个线程跑跑看。
并行的线程却是是颠三倒四的。。所以我怀疑你到底想用它干啥。。
Dao并发过高,那么就会等待连接池有空余连接吧(看配置),适当调大一些poolsize就好
看到最后一句话,我知道你的问题在哪了。。
new thread并不是连接池中的线程!!!你for多少次都是最大15个线程,空闲线程看负载多大
连接池中的线程是在datasource.queryXXX的时候拿conn的。。
嗯呐好感动回答的真详细~问题已经解决了,通过修改acquireIncrement=1,最多只会产生10个连接。
看来我这种测试并发的方法太非主流了,求主流方法~
以及您是否了解dao的设计思路应该怎么应对好并发呢?就是那种并发数远大于db连接池最大数的时候,dao应该做的
【 在 ml3615556 的大作中提到: 】
: 产生多于十个连接可能是连接池自己初始化了多于10个,你设置不允许连接池有空闲conn试试?
: 至于为什么每次打出来连接池个数不一样,我猜,是因为连接池是默认lazy-init的,你一边用连接它一边给你初始化连接,要证实这个说法,你可以在sleep后面再开10个线程跑跑看。
: 并行的线程却是是颠三倒四的。。所以我怀疑你到底想用它干啥。。
那个acquirement修改了用处不大。。保持空闲的连接是很有必要的,所以恐怕你提出的解决问题实际上是解决一个不是问题的问题
随便说几个。。基本很多人都知道的,随便搜索一下会更全
优化你的sql,优化你的表结构与策略,这样来减小连接池数据库压力
加大你的连接池
引入集群来处理高并发
【 在 echojessicaa 的大作中提到: 】
: 嗯呐好感动回答的真详细~问题已经解决了,通过修改acquireIncrement=1,最多只会产生10个连接。
: 看来我这种测试并发的方法太非主流了,求主流方法~
: 以及您是否了解dao的设计思路应该怎么应对好并发呢?就是那种并发数远大于db连接池最大数的时候,dao应该做的
嗯…你的建议是为了扩充了数据库处理能力,提高最大连接数量;而我的问题是连接数无论多大都会遇到超出的那个场景,那个场景应该遵循什么原则处理呢,只能抛出异常并操作失败?是否已经有比较成熟的解决原则和解决方案呢
【 在 ml3615556 的大作中提到: 】
:
: 那个acquirement修改了用处不大。。保持空闲的连接是很有必要的,所以恐怕你提出的解决问题实际上是解决一个不是问题的问题
:
当连接数不够时,新来的数据库查询操作请求会被阻塞,直到有空闲连接出现。
如果服务器吞吐量不够,过多的阻塞会让服务器挂掉。
这种规模的并发量,我还没遇到过
估计让服务器消极的处理被阻塞的线程,控制阻塞队列长度,让无法处理的请求直接抛请求失败吧
我还是感觉你的并发量不可能有你描述的那么夸张,这种级别的并发量不是小公司遇得到的[em4]
【 在 echojessicaa 的大作中提到: 】
: 嗯…你的建议是为了扩充了数据库处理能力,提高最大连接数量;而我的问题是连接数无论多大都会遇到超出的那个场景,那个场景应该遵循什么原则处理呢,只能抛出异常并操作失败?是否已经有比较成熟的解决原则和解决方案呢
: :