Tomcat DBCP连接池导致的线程阻塞问题

  • 问题描述
  • 解决流程

问题描述

最近在测试一个多线程任务时出现了我本地项目不报错,不停止,但是刷新任何的页面或者重新加载整个网站服务都无法继续执行操作的问题,也就是界面无响应,后台日志无输出且不报错卡死的情况。

解决流程

日志无法输出,因此查看了JVM线程堆栈的信息,怀疑时死锁的问题,在Jconsole中查看是否死锁现象。检测发现当前的所有线程都没有死锁存在,所以拖出来了日志,发现当前显示出来的所有状态不是 WAITING 就是 TIMED_WAITING ,不存在(运行状态的线程),不存在死锁那么就可能是线程阻塞了,日志显示大部分的线程都在等待 0x00000006d057ce08 这个资源,如下图所示:

"taskExecutor-3" #1158 prio=5 os_prio=0 tid=0x0000000032317800 nid=0x50e4 waiting on condition [0x000000008e72e000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000006d057ce08> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at org.apache.tomcat.dbcp.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:586)at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:438)at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:359)at org.apache.tomcat.dbcp.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134)at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1543)at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:246)at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)at com.hand.hap.task.service.impl.ExecuteServiceImpl$TaskThread.run(ExecuteServiceImpl.java:89)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)"taskExecutor-2" #1156 prio=5 os_prio=0 tid=0x000000003230f800 nid=0x460 waiting on condition [0x000000008e62f000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000006d057ce08> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at org.apache.tomcat.dbcp.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:586)at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:438)at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:359)at org.apache.tomcat.dbcp.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134)at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1543)at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:246)at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)at com.hand.hap.task.service.impl.ExecuteServiceImpl$TaskThread.run(ExecuteServiceImpl.java:89)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)"TASK-31825" #1154 prio=5 os_prio=0 tid=0x000000003232f800 nid=0x4208 waiting on condition [0x000000008e32d000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000006d057ce08> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at org.apache.tomcat.dbcp.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:586)at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:438)at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:359)at org.apache.tomcat.dbcp.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134)at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1543)at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:246)at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447)at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277)at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)at com.sun.proxy.$Proxy731.updateProcessStatus(Unknown Source)at fms.xxmpl.biz.service.impl.MplTaskExecutionServiceImpl.batchManuscriptTaskExecute(MplTaskExecutionServiceImpl.java:169)at sun.reflect.GeneratedMethodAccessor3371.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45005)at com.zeroturnaround.jrebelbase.facade.Forward.methodInvoke(SourceFile:247)at java.lang.reflect.Method.invoke(Method.java:498)at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)at com.hand.hap.core.impl.ServiceExecutionAdvice.invoke(ServiceExecutionAdvice.java:126)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)at com.sun.proxy.$Proxy731.batchManuscriptTaskExecute(Unknown Source)at fms.xxmpl.biz.task.components.BatchManuscriptTask.execute(BatchManuscriptTask.java:32)at com.hand.hap.task.service.impl.ExecuteServiceImpl$TaskThread.operateExecutionInfo(ExecuteServiceImpl.java:225)at com.hand.hap.task.service.impl.ExecuteServiceImpl$TaskThread.executeTask(ExecuteServiceImpl.java:148)at com.hand.hap.task.service.impl.ExecuteServiceImpl$TaskThread.execute(ExecuteServiceImpl.java:120)at com.hand.hap.task.service.impl.ExecuteServiceImpl$TaskThread.run(ExecuteServiceImpl.java:96)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)

但是并没有找到占用这个资源的而进程,不太方便定位问题的所在,看到下面的问题:

并且执行日志卡在了创建新的 sqlSession的日志处,之后就不在继续输出了,因此考虑是否是因为申请不到连接池的原因,导致线程阻塞的问题,再加上测试环境可以正常执行我的多线程任务,因此首先以为是数据库的原因:
1.是否是无法获取数据库的连接,查看了对应的数据库的当前连接数,以及最大连接数,使用量处于一半以下。不是该问题
2.是否是数据库锁表导致申请不到对应的资源,因此查看数据库是否缩表,也不是该问题

结合上面的日志参考测试环境的配置猜测可能是Tomcat配置的问题,Tomcat的连接池资源不够,因为Jconsle中执行程序的线程数上去之后就降不下来,线程本地的Context.xml文件中并没有配置配置相关的回收机制,和超时的处理机制,导致一直无限的 WAITING(线程的该状态表示无限期等地资源) 资源。

本地context.xml的配置是:

<Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@xx.xx.xx.xx:1531:SIT" name="jdbc/hfms_dev" type="javax.sql.DataSource" username="username" password="password"/>

看了sit的配置去了解了一下Tomcat使用的连接池: DBCP连接池,可以在里面配置数据库的连接以及对连接超时的处理情况,之后更改配置如下:

<Resource auth="Container" type="javax.sql.DataSource" name="jdbc/hfms_dev" driverClassName="oracle.jdbc.driver.OracleDriver"url="jdbc:oracle:thin:@xx.xx.xx.xx:1531:SIT" username="username" password="password"maxWaitMillis="30000"maxTotal="3000"removeAbandonedOnBorrow="true" removeAbandonedOnMaintenance="true" removeAbandonedTimeout="180" />

maxWaitMillis=“30000” 连接最长的等待时间 ,单位是 毫秒 也就是 30 秒
maxTotal=“3000” 连接最大的总数: 3000

    **以下是用来配置数据库断开后自动连接的**removeAbandonedOnBorrow="true"  removeAbandonedOnMaintenance="true" removeAbandonedTimeout="180"    等待移除的连接的超时时间 180s

Tomcat DBCP连接池导致的线程阻塞问题相关推荐

  1. CountDownLatch导致的线程阻塞问题及线程池的使用

    CountDownLatch导致的线程阻塞问题及线程池的使用 CountDownLatch是什么 countdownlatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完 ...

  2. DBCP连接池原理分析

    DBCP连接池介绍 ----------------------------- 目前 DBCP 有两个版本分别是 1.3 和 1.4. DBCP 1.3 版本需要运行于 JDK 1.4-1.5 ,支持 ...

  3. Linux主机熵值不足导致SecureRandom线程阻塞问题

    Linux主机熵值不足导致SecureRandom线程阻塞问题 linux操作系统熵值不够,导致使用安全随机数时,长时间线程阻塞. 问题定位 使用jdk远程debug,发现线程堆栈停在SecureRa ...

  4. DBCP连接池耗尽问题

    问题描述 使用DBCP连接池.每当访问数据库超时,永久占用数据库连接池的一个连接数.多次超时发生后,数据库连接池耗尽,后续的数据库请求拿不到数据库连接,全部hang住. 代码分析 1 数据库访问获取连 ...

  5. 在独立Java应用程序中使用Tomcat JDBC连接池

    这是从我们的客人文章W4G伙伴克拉伦斯豪的作者临春3从A按. 您可能会在文章结尾找到本书的折扣券代码,仅适用于Java Code Geeks的读者! 请享用! 在需要数据访问权限的独立Java应用程序 ...

  6. basicdatasourcefactory mysql_Java基础-DBCP连接池(BasicDataSource类)详解

    Java基础-DBCP连接池(BasicDataSource类)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际开发中"获得连接"或"释放资源 ...

  7. DBCP连接池配置常用参数说明

    参数 默认值 说明 username \ 传递给JDBC驱动的用于建立连接的用户名 password \ 传递给JDBC驱动的用于建立连接的密码 url \ 传递给JDBC驱动的用于建立连接的URL ...

  8. java配置dbcp连接池(数据库连接池)示例

    最近一个项目遇到了一个问题,tomcat跑一段时间后,项目就会造成类似死锁状态,所有的servlet都无法访问,造成网络堵塞的现象.我项目中使用的连接池是c3p0,网上有人说是c3p0的bug,不知是 ...

  9. java dbcp连接池_Java——DBCP连接池

    连接池 实际开发中"获得连接"或"释放资源"是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection.这样 ...

最新文章

  1. MyBatis Mapper 文件例子
  2. 【软件工程】CMMI 能力成熟度模型集成 ( 简介 | 相关术语 | CMMI 等级评估次序 )
  3. 访问数据库_访问数据库
  4. leetcode 225. 用队列实现栈(维护两个队列用于倒替元素,使用和1进行按位与,实现队列切换)
  5. java 3number_java 数据Number、Math
  6. linux中常用的头文件
  7. Linux Shell脚本之利用mysqldump备份MySQL数据库(详细注解)
  8. [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)...
  9. (日常搬砖)windows 11 安装cython_bbox时,遇到问题‘error: Microsoft Visual C++ 14.0 or greater is required. ’解决方案
  10. 父组件直接触发子组件中的函数
  11. phpcms V9.6.0版本整合百度ueditor1.4.3.2,包括水图片上传水印
  12. 高斯勒让德数值积分公式
  13. QTP之reporter对象方法全解析
  14. 阿里云 OSS浏览器使用步骤
  15. PB AcceptText()函数
  16. 索尼公布电池召回计划 不局限于笔记本
  17. C语言之打印错误信息
  18. 数据之美(九):50个精美绝伦的 Infographics(上)
  19. 计算机文化基础(高职高专版 第十一版)第一章答案
  20. Matlab数据统计与分析(四)——参数估计

热门文章

  1. Python Pdb源码解析
  2. windows系统下的文件夹链接功能mklink/linkd
  3. 【解答】命令行(Cmd/Powershell)从默认C盘切换到其他盘(D盘)包括转到C盘
  4. HTTP请求中POST与GET的区别
  5. 查询所有上级和所有下级
  6. ios 11 屏幕适配问题!
  7. USACO2011Open Silver Running Laps题解
  8. 大数据早报:甲骨文公司投资4300万美元在总部建高中 18项全球互联网领先科技成果公布中国占6成 (12.6)...
  9. 配置haproxy支持使用多个lan内网ip做负载均衡以突破haproxy机只支持64k连接(突破单ip 65535端口限制)
  10. Swift-UITableView快捷创建(刨坟用)