博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
原 荐 cache线程池对数据库操作的饥饿问题
阅读量:4290 次
发布时间:2019-05-27

本文共 933 字,大约阅读时间需要 3 分钟。

最近的工作中,因为程序需要大量进行数据库查询,我使用ArrayBlockingQueue模仿数据库连接池,里面初始化了固定数量的数据库连接对象。

我的业务中,存在主任务生成子任务,然后通过Future对象等待子任务返回结果的情况,为了避免已经在work队列的主任务一直占着cpu等待子任务返回,而子任务由于在task队列中,因此得不到cpu资源,无法执行。我使用了cache线程池,让所有任务都能被封装为thread,可以得到cpu时间。

这个设计在测试环境的小数据集下运行是正常的,任务都能执行完,但提交到生产环境,就会在运行一段时候后出问题,现象是程序日志停止,对象gc也停止,似乎程序停止或者在被阻塞住了。

后来通过jstack命令,将程序的线程调用栈帧拿来分析发现大量的线程是处于packing状态,而且他们都是在ArrayBlockingQueue的take方法上阻塞,数量有436个。

原 荐 cache线程池对数据库操作的饥饿问题

因此怀疑,可能是有方法将A连接池中的dbHelper用完后,放到了B连接池中,导致最后A连接池中dbHelper全部泄露到了其他地方,因此没有线程能再获取到数据库连接。但对代码检查后,没有发现这种问题。

接下来再看线程栈帧,发现线程cache线程池的线程id已经到了893,证明cache线程池中有大量线程生产,这些线程都处于packing状态。只有一个线程是runnable状态,他获得了dbHelper,正在查询数据库。

原 荐 cache线程池对数据库操作的饥饿问题

于是我怀疑,是因为生成了大量线程,这些线程都需要分配cpu时间才能执行,但每个线程都只能分配到很少的cpu时间,导致持有dbHelper的线程迟迟执行不完,它无法释放dbHelper,其他线程也只能浪费着cpu时间等着。

接下来修改代码,主任务还是在cache线程池中,但其产生的子任务,放到另外一个fix线程池中执行,这样cpu就会将fix的worker队列中的查询先执行完,将dbHelper还回连接池,再去执行新的子任务,而不会创建过多的thread去等待dbHelper。修改完成后,重新执行程序,终于在日志中发现了新的日志,问题被解决。

其实到最后,我也不知道自己的分析是否完全正确。

转载地址:http://etggi.baihongyu.com/

你可能感兴趣的文章
springmvc整合poi导出报表
查看>>
Oracle Data Guard延迟的原因
查看>>
java8 遍历数组的几种方式
查看>>
java基础知识(七)--Object类
查看>>
Object.prototype.toString_优就业
查看>>
JS之浏览器对象BOM
查看>>
分布式架构系列: 负载均衡技术详解
查看>>
python3安装scrapy
查看>>
python正则表达式入门一
查看>>
python正则表达式入门二
查看>>
scrapy运行
查看>>
XPATH入门
查看>>
python爬虫 CSS选择器
查看>>
正常关闭java程序
查看>>
查看linux核心数
查看>>
数据结构与算法三: 数组
查看>>
Activiti工作流会签二 启动流程
查看>>
Activiti工作流会签三 撤销,审批,驳回
查看>>
Oauth2方式实现单点登录
查看>>
CountDownLatch源码解析加流程图详解--AQS类注释翻译
查看>>