2012-08-09 91 views
0

我在我的应用程序中有一个以下工作流程:可以有来自用户的X请求(通常是5-10个)想要在系统中搜索某些内容的请求(每个请求都在单独的线程中处理)。动态调整大小的线程池

每个搜索可以并行处理(我目前正在实施)。线程/ CPU使用率并不是真正的问题,因为这些任务不是CPU密集型的。数据库是瓶颈。

目前我为搜索机制设置了一个单独的数据库连接池 - 最大池大小设置为10.我知道这并不多,但我无法将其设置得更高。现在我试图找出如何为每个搜索(每个用户)设置线程池。

每个请求(线程)将产生一个单独的线程池(并在此池中每个线程将处理给定用户搜索的一部分)。如果例如10个用户一次点击“搜索”按钮,将该线程池的大小设置为固定大小(可以说4)是真正有问题的,因为它会产生10个线程池,每个线程4个线程,每个线程40个线程,并且只有10个线程池数据库连接在池中?我想有些线程会简单地闲置,其余的则会争夺游泳池的连接,但这真的是一个巨大的问题?

如果是,那么这将是最好的行动路线:

  1. 检查多少线程池目前已经有在创建 新的,并相应地调整它的(新池的)最大线程池的大小(比如说 已经有2个池,每个池有4个线程,然后新创建的最大线程数被设置为2的新的池将被创建,甚至更新的池可以说只有1个最大线程)。这意味着每个下一个用户的搜索会显着变慢。
  2. 创建具有相同最大线程池大小(即4)的线程池,但实现我自己的线程池,它可以动态检查应用程序中有多少线程,并相应地调整maxThreadPoolSize的大小(在本例中为所有线程池, 2个旧的和新的,将会缩小以允许说3个线程)。这将要求每个线程池访问某个包含应用程序中所有线程池信息的共享对象。
  3. 别的东西?

编辑: 感谢所有的意见/答案。为了说明为什么我希望每个请求有一个线程池 - 这样做是为了让一个用户不会占用整个线程池。流程完全是这样的:当用户点击“搜索”时,会生成一个对象列表(该列表可以从1个项目到几千个),然后为每个项目执行一次数据库查找。现在它全部按顺序执行。我的更改后,每个任务处理一个查找(因为在数据库上的搜索很慢,它给了我一个非常巨大的提升 - 我知道我可以尝试做一些数据库微调,但我不负责它)。

问题是,如果我User1来执行一个真正的通用搜索X千生成的项目它可能需要几分钟(或更多)。所以我可以从单个用户那里执行数千个任务。然后,如果我有一个共享线程池,可以说最多10个线程(与连接池的数量相同),则该请求将放入线程池的队列中。现在,如果User2来执行搜索,他将不得不等待User1的搜索完成,因为他的搜索将被放入同一个队列。这是我想避免线程池每个请求的情况。

我真的不那么害怕上下文切换,因为每个计算可能需要几秒钟,所以他们不会经常发生。

目前我正在思考一个共享线程池和经理为每个用户线程会派他的数据,然后该经理将其发送到线程池时会有空闲线程。这样我就可以实现它(管理器)发送来自不同用户的任务(即没有一个用户不会支配线程池)。

我用这种方法看到的问题是,我需要以某种方式告知“父线程”(意为用户请求),它的所有任务由经理处理,并以某种方式把它的结果。

+3

为什么不使用单个共享线程池而不是1 /请求? – 2012-08-09 13:17:49

+0

你只执行搜索吗? – Edmondo1984 2012-08-09 13:19:49

+0

@Matt Ball:这是一个很好的问题:)认为我有一个理由,但我需要重新考虑这一点。 – 2012-08-09 13:20:36

回答

1

现代处理器可以轻易地用没有问题的线程百十来处理,但作为@PeterLawrey曾建议有一些奇怪的事情与你的设计。正如你所说的,如果操作的计算花费不大,那么线程数量非常大会导致大量昂贵的上下文切换,从而导致性能下降。

额外的复杂性来自于你想有一个线程池为每个请求,而连接池是每个应用程序的事实:

  • 如果每个请求的线程池,你会创建它并在每次获得新请求时销毁
  • 无论数十万线程和超级计算机拥有100000美元的预算,您将拥有不超过10个线程将执行有用的工作。

你的直觉应该现在告诉大家,问题是,你想有一个线程池为每个请求,而理想的解决方案是让请求之间共享的线程池,线程等于你的连接数游泳池大小。这将最大化线程重用。

如果你也想避免一个请求采取一切你的计算能力,你可能需要添加它决定谁有权安排额外的工作权的层。使用每个请求解决方案的线程池,您可以让调度程序为您执行该操作,而这不是一个好主意,因为您不控制算法。

相反,您可以通过PriorityBlockingQueue来实现您自己的“公平算法”,例如通过PriorityBlockingQueue(其中块的数量较少的项目位于顶部),或者使用ConcurrentHashMap来为每个用户存储要调度的作业列表,已经返回的人等等。

+0

感谢您的输入,但我对我在编辑中添加的共享线程池解决方案有一些疑虑。 – 2012-08-09 14:15:43

+0

谢谢埃德蒙多,我也在考虑ConcurrentHashMap,所以我想我会去用它。 – 2012-08-09 16:18:02