论坛首页 综合技术论坛

逻辑划分线程池-任务池

浏览 2033 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-05-22  

服务端编程里,线程池的使用非常普遍。往往是按照逻辑划分为不同的线程池。这种做法存在一个问题,对每个线程池的利用都是局部的,缺少一个全局限制的目标。

 

希望能有一种任务池的机制,多个任务池共享一个线程池,每个任务池可配置并发执行的能力,主要有两个参数,固定为该任务池服务的线程数和峰值时可弹性增加的线程数。

 

在网上发现类似的两篇文章,放翁(文初)的《逻辑划分线程池》和淘宝博客上一篇《支持配额的共享线程池》。看了一下,对任务池(暂且都叫任务池)的看法都差不多,前者的“保留数”和后者“固定配额”都是固定分配给一个任务池的线程数。前者的“限制数”和后者的“弹性配额”是动态申请数。但是在实现,两者有一点区别(更详细的大家可把他们的代码下来研究下)。下面简单说一下两者的实现。

 

前者全局有一个任务队列,提交任务时,判断对应的任务是否能被执行,如果可以则提交到线程池,否则,提交到任务队列。有一个额外的后台提交任务的工作线程,不断从任务队列里取任务,做提交任务的操作,如果任务不能被提交到线程池,则会再放回任务队列。在某些情况下,这个提交任务的工作线程可能遍历整个队列才能找到可以被提交的任务。甚至是在空转,假如任务队列的任务都是不能被提交的。然后还有一个取出的任务为空,睡眠一小段时间,这个时间具体大小也是一个比较难确定的值。

 

        后者也有一个全局的任务队列,提交任务时,判断对应的任务是否能被执行,如果可以则提交到线程池,否则,提交到任务队列。那么,任务队列的任务什么时候再提交到线程池,作者没有使用额外的线程,当提交到线程池的一个任务执行结束后,加了一个顺带从任务队列取任务提交到线程池的操作。注意,在这里,这个提交操作没有再判断该任务是否超过它的配额。作者这里把它简单化了,任务队列是一个优先级的队列,固定配额较大的任务的优先级较高。这种处理方法可能也会导致一种任务的并行执行数超过它的实际配额。

 

看了两者的实现,和自己的需求还是有点距离,前者的后台工作线程在某些情况可能效率比较低,后者的对于任务的限制也存在一些缺陷。两者有一个共同点是通过判断,再把任务提交到线程池,提交到线程池的任务就是可执行的。对于任务池的需求,这种处理方法不太好实现或是实现的不完全。那么能否换个思路,不把任务直接提交到线程池,,只提交取任务的操作到线程池。

 

个人思路:

1. 共享线程池,逻辑划分为任务池,每个任务池配置固定配额和弹性配额。

2. 每个任务池有自己的任务队列,提交到任务池的任务先提交到对应的任务队列。

3. 创建任务池时,如果有固定配额,提交固定配额任务到线程池,固定配额任务不会释放线程,它的操作是不断 从任务队列取任务执行。

4. 提交任务时,判断如果需要执行申请弹性配额,提交弹性配额任务到线程池。弹性配额任务尝试从任务队列取 任务,如果为空则释放线程。

 

这样处理能比较好的实现任务池的需求。多任务队列带来一个额外的好处是,减少对线程池的任务队列的争用。把多个线程池合并成一个任务池,执行任务的线程数也多了,如果底层仍然用一个任务队列,对这个任务队列操作是一个热点。使用多任务队列,不是所有的任务最终都提交到线程池的任务队列,只有需要弹性配额时才提交。

 

郁闷,google-code的密码页面打不来。第一版的实现见附件。

论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics