ExecutorService 导致 JDBC 连接问题
Posted
技术标签:
【中文标题】ExecutorService 导致 JDBC 连接问题【英文标题】:ExecutorService causes JDBC connection Issue 【发布时间】:2015-09-17 14:51:11 【问题描述】:许多 JDBC 调用(查询 DB 和获取结果)都是通过 ExecutorService 执行的。我发现当执行这些调用时,JDBC 连接需要很长时间才能关闭连接,即使这些连接已正确关闭。为什么我这么说是,当通过JMeter运行负载测试时,数据库显示很多连接在IDLE in transaction
。如果运行测试的线程数很高,则事务中空闲的连接数会增加。如果测试运行缓慢,则连接会慢慢关闭(1、2 分钟),这意味着事务中有 IDLE 连接,但几分钟后它们变为 IDLE。我也在这里使用连接池。如果我将 JDBC 查询函数作为一个序列(一个接一个)运行,那么数据库不会在事务中的 IDLE 中显示任何连接。下面是我如何运行运行 JDBC 查询的可运行任务。 TaskManager 类处理整个 ExecutorService 相关的功能。
public class TaskManager
final private ThreadServiceFactory threadFactory;
private int concurrentThreadCount;
private ExecutorService executerSV;
private final CountDownLatch latch;
// I keep a count of proposed tas task as servicecount
public TaskManager(int serviceCount)
threadFactory = new ThreadServiceFactory();
this.concurrentThreadCount = serviceCount;
latch = new CountDownLatch(serviceCount);
public void execute( ThreadService runnableTask)
Object rv = null;
runnableTask.setCountDownLatch(latch);
if(executerSV == null)
executerSV = Executors.newFixedThreadPool(this.concurrentThreadCount, getThreadFactory());
executerSV.execute(runnableTask);
public boolean holdUntilComplete()
try
latch.await();
executerSV.shutdown();
return true;
catch (InterruptedException e)
e.printStackTrace();
return false;
private ThreadServiceFactory getThreadFactory()
threadFactory.setDeamon( Boolean.FALSE);
return threadFactory;
在我的测试课上;
public void test()
TaskManager tm = new TaskManager(3);
tm.execute(queryTask1);
tm.execute(queryTask2);
tm.holdUntilComplete();
queryTask1 是一个 Runnable,它调用 JDBC 选择查询。
如果我运行queryTask1.run(); queryTask2.run();
,那么数据库中的连接中没有任何空闲。
我使用java 7。请任何人告诉我问题出在哪里。
【问题讨论】:
【参考方案1】:您的问题中没有任何代码可以打开与数据库的任何连接。因此,很难提出答案。但是,由于您声明您正在使用连接池,因此您应该更好地查看池配置参数,因为它们决定了空闲连接在被驱逐之前可以打开多长时间。例如,如果您在 tomcat 中运行连接池,则应特别查看“minIdle”、“maxIdle”和“minEvictableIdleTimeMillis”属性。见https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
【讨论】:
感谢您的回答。当我一个接一个地运行 JDBC 调用(没有 ExecutorService)时,DB 中没有这样的“IDLE in transaction”连接。这是否意味着 JDBC 调用或池配置没有问题?我以多种方式尝试了我的代码,最后一项更改是更改了这些使用 Executor 运行的任务的方式,而没有,我发现,在作为序列运行时,事务中的 IDLE 不会出现。 不客气。如果没有您正在做的事情的更多详细信息(您正在运行的查询,您正在使用的 DBMS),我认为我不会有太大的帮助,但看起来您的查询存在并发问题。这篇文章 (serverfault.com/questions/660642/…) 描述了一个类似的问题,并暗示问题可能出在代码本身,例如事务正在启动但从未完成。请注意,如果您按顺序运行事务,则可能不会出现此类问题,就像您的情况一样。以上是关于ExecutorService 导致 JDBC 连接问题的主要内容,如果未能解决你的问题,请参考以下文章
Android线程管理之ExecutorService线程池
Oracle JDBC 驱动程序未在旧版 Web 应用程序中使用 JNDI 连接到数据库
ExecutorService对象的shutdown 和shutdownNow 的区别
JDK 源码解析 —— Executors ExecutorService ThreadPoolExecutor 线程池