我很想知道在以下情况/约束下,是否存在一种在线程池中管理线程资源的广泛接受的解决方案:

  • 传入的工作都是一样的
    自然,可以由任何人处理
    池中的线程。
  • 即将到来的工作
    将被“桶化”成不同的
    基于以下属性的队列
    即将到来的工作,以便所有工作
    必须转到相同的存储桶/队列
    串行处理。
  • 有些存储桶的忙碌程度不如
    其他人在不同的时间
    程序的生命周期。

  • 我的问题是关于线程池实现背后的理论。可以使用哪种算法有效地将可用线程分配给所有存储桶中的传入作业?

    编辑:另一个设计目标是在假定有可用的空闲线程的情况下,尽可能减少排队的作业与拾取的作业之间的等待时间。

    Edit2 :在我考虑的情况下,有相对大量的队列(50-100)具有不可预测的 Activity 级别,但是在任何给定时间可能只有25%的队列处于 Activity 状态。

    我想到的第一个(也是最昂贵的)解决方案是简单地为每个队列分配一个线程。虽然这将确保传入的请求立即得到处理,但效率显然很低。

    第二种解决方案是根据预期的 Activity 级别将队列组合在一起,以使队列的数量与池中的线程数量一致,从而允许为每个队列分配一个线程。这里的问题是,传入的作业(否则可以并行处理)将被迫彼此等待。

    第三种解决方案是创建最大数量的队列,每组必须串行处理的队列一个,但是只能根据我们希望在任何给定时间忙碌的队列数量来分配线程(也可以通过以下方式进行调整:运行时池)。因此,这就是我的问题所在:鉴于我们队列中的线程多于线程,池如何以最有效的方式将空闲线程分配给传入的作业?

    我想知道是否有一种被广泛接受的方法。或者,如果有不同的方法-谁使用哪种方法?优点/缺点是什么?

    Edit3 :最好用伪代码表示。

    最佳答案

    您可能应该消除nr。 2从您的规范。您真正需要遵守的是线程占用存储桶并按顺序处理存储桶中的队列。用另一个线程池处理序列化队列或并行执行一些任务序列化是没有意义的。因此,您的规范就变成了线程迭代存储桶中的fifo,并且由poolmanager来插入正确构造的存储桶。因此,您的存储桶将是:

    struct task_bucket
    {
        void *ctx; // context relevant data
        fifo_t *queue; // your fifo
    };
    

    然后,由您决定使线程池足够智能,以知道在每次队列迭代时要做什么。例如,ctx可以是一个函数指针,并且队列可以包含该函数的数据,因此工作线程仅在每次迭代时使用提供的数据调用该函数。

    反射(reflect)评论:
    如果存储区列表的大小是事先已知的,并且在程序的生命周期内不太可能更改,则需要确定这对您是否重要。您将需要某种方式让线程选择要使用的存储桶。最简单的方法是让FIFO队列由管理器填充并由线程清空。经典的读者/作家。

    另一种可能性是堆。工作进程从堆中删除最高优先级,并处理存储桶队列。由工作人员删除和由管理者插入都对堆重新排序,以使根节点具有最高优先级。

    这两种策略均假设 worker 丢掉了水桶,而经理则制造了新桶。

    如果保留存储桶很重要,则冒着工作人员仅参加最后修改的任务的风险,因此管理器将需要重新排序存储桶列表或修改每个存储桶的优先级,并且工作人员会迭代以寻找最高优先级。重要的是,在线程正在工作时ctx的内存保持相关性,否则线程也必须复制它。工作人员只需在本地分配队列,然后在存储桶中将队列设置为NULL。

    关于multithreading - 线程池多队列作业分配算法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5932712/

    10-09 00:46