【发布时间】:2012-08-06 17:34:36
【问题描述】:
我的应用程序中有以下工作流程:可能有来自用户的 X 个请求(通常同时有 5-10 个)想要在系统中搜索某些内容(每个请求都在单独的线程中处理)。
每个搜索都可以并行处理(我目前正在实施)。线程/CPU 使用在这里并不是真正的问题,因为这些任务不是 CPU 密集型的。数据库是瓶颈。
目前我只为搜索机制设置了一个单独的数据库连接池 - 最大池大小设置为 10。我知道这并不多,但我不能将它设置得更高。现在我想弄清楚如何为每个搜索(每个用户)设置线程池。
每个请求(线程)都会产生一个单独的线程池(在这个池中每个线程将处理给定用户搜索的一部分)。如果例如 10 个用户一次点击“搜索”按钮,将这个线程池的大小设置为固定大小(假设为 4)真的会有问题,因为它会产生 10 个线程池,每个线程池有 4 个线程 = 40 个线程并且只有 10 个池中的数据库连接?我猜有些线程只是空闲,其余线程会竞相获得池的连接,但这真的会是个大问题吗?
如果是,那么最好的做法是什么:
- 在创建线程池时检查已有多少线程池 新的并相应地调整其(这个新池的)最大线程池大小(比如 已经有 2 个池,每个池有 4 个线程,那么新的池将 将最大线程设置为 2 甚至更新的池(假设只有 1 个最大线程)创建。这意味着下一个用户的搜索速度会大大降低。
- 创建具有相同最大线程池大小(即 4)的线程池,但实现我自己的线程池,它将动态检查应用程序中有多少线程并相应地调整 maxThreadPoolSize 大小(在这种情况下,例如所有线程池, 2 个旧的和新的,将缩小到 3 个线程)。这将要求每个线程池访问某个共享对象,其中包含有关应用程序中所有线程池的信息。
- 还有别的吗?
编辑: 感谢所有 cmets/答案。为了澄清为什么我想要每个请求都有一个线程池 - 这样做是为了让一个用户不会用完整个线程池。流程是这样的:当用户点击“搜索”时,会生成一个对象列表(这个列表可以从 1 个项目到数千个),然后为每个项目执行一个 DB 查找。现在这一切都是按顺序执行的。在我更改后,每个任务都会处理一次查找(因为在 DB 上的搜索速度非常慢,这给了我很大的提升 - 我知道我可以尝试做一些 DB 微调,但我不负责)。
问题是,如果我 User1 来并执行一个真正通用的搜索 X 千生成的项目可能需要几分钟(或更长时间)。因此,我可以在单个用户的 executor 中执行数千个任务。然后,如果我有一个共享线程池,可以说最多 10 个线程(与连接池的数量相同),这个请求将被放入线程池的队列中。现在,如果 User2 来执行他的搜索,他将不得不等待 User1 的搜索完成,因为他的搜索将被放入同一个队列中。这是我想通过每个请求的线程池来避免的情况。
我并不是真的那么害怕上下文切换,因为每次计算可能需要长达几秒钟的时间,所以它们不会经常发生。
目前我正在考虑一个共享线程池和一个管理器,每个用户线程会将其数据发送到该管理器,然后只要有空闲线程,该管理器就会将其发送到线程池。这样我就可以实现它(管理器)来发送来自不同用户的任务(即没有一个用户不会控制线程池)。
我看到这种方法的问题是我需要以某种方式通知“父线程”(即用户请求)它的所有任务都由经理处理并以某种方式将结果发送给它。
【问题讨论】:
-
为什么不使用单个共享线程池而不是 1/request?
-
您只执行搜索吗?
-
@Matt Ball:这是一个很好的问题 :) 认为我有一个理由,但我需要重新考虑这一点。
-
如果每个请求已经有一个线程,则根本不需要额外的池。您需要一个用于 10 个并发数据库会话的连接池。
-
是的,但是如果有一个共享线程池,一个用户就不可能支配整个线程池吗?
标签: java parallel-processing threadpool