我有一个Java批处理,它对一个大结果集进行选择(我使用Spring回调处理程序处理元素)。 回调处理程序将任务放入固定线程池中来处理该行。 我的池大小固定为 16 个线程。 结果集包含大约 100k 元素。 所有数据库访问代码均通过 JdbcTemplate 或 Hibernate/Spring 处理,不存在手动连接管理。 我尝试过使用 Atomikos 和 Commons DBCP 作为连接池。
现在,我认为连接池中的最大连接数为 17 个就足以完成该批处理。 1 个用于选择,16 个用于连接池中更新某些行的线程。然而,这似乎太天真了,因为我必须指定一个更大的最大池大小(没有尝试过确切的值),首先我尝试了 50,它在我的本地 Windows 机器上工作,但在我们的 Unix 测试环境上似乎不够。我必须指定 128 才能使其工作(同样,我什至没有尝试 50 到 128 之间的值,我直接选择了 128)。
这正常吗?我缺少连接池中的一些基 native 制吗?我发现很难调试它,因为我不知道如何查看打开的连接会发生什么。我尝试了各种 log4j 设置,但没有得到任何满意的结果。
编辑,附加信息:当连接池大小似乎太低时,批处理似乎会挂起。如果我对进程执行 jstat,我可以看到所有线程都在等待新连接。起初,我没有在 dbcp 连接池上指定 maxWait 属性,这会导致线程无限期地等待新连接,并且我注意到批处理一直挂起。所以没有释放任何连接。然而,这只发生在处理 +-70k 行之后,这以某种方式消除了我最初的连接泄漏预感。
edit2:我忘了提及我已经重写了任务中的更新部分。我在 ConcurrentLinkedQueue 中 qeueu 更新,然后清空 1000 个元素。所以我实际上只做了大约 100 次更新。
edit3:我正在使用 Oracle,并且正在使用并发实用程序。所以我有一个配置了固定池大小 16 的执行器。我在这个执行器上提交我的任务。我不会在任务中手动使用连接,我使用线程安全的 jdbctemplate 并要求它从连接池中获取连接。我想 Spring/DBCP 处理连接/线程问题。
最佳答案
如果您使用的是Linux,您可以尝试使用MySql管理员以图形方式监控您的连接状态,前提是您使用的是MySQL。
无论如何,对于大型企业应用程序来说,即使 100 个连接也并不罕见,每分钟处理几千个请求。
但是如果请求较低或者每个请求不需要唯一的事务,那么我建议您调整线程内的操作。
也就是说,你如何将 100k 元素分配给 16 个线程? 如果每次从共享位置(或缓冲区)读取一行时都尝试获取连接,则预计需要时间。
看看这是否有帮助。
- 获取连接
- 对于每个元素,直到缓冲区大小变为零
- 处理它。
- 如果您需要更新,
- 开启交易
- 更新
- 提交/回滚事务
- 转到步骤 2
- 释放连接
您可以使用java.util.concurrent collections来同步缓冲区
不要为每个元素使用一个 Runnable/Callable。这会降低性能。 另外你是如何创建线程的?使用 Executors 来运行您的可运行/可调用。另请记住,数据库连接不应跨线程共享。因此,一次在 1 个线程中使用 1 个连接。
例如。创建一个 Executor 并提交 16 个 runnalble,每个 runnalble 都有自己的连接。
关于java连接池,多线程批处理中的最大连接数是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9503930/