处理线程池中具有不同优先级的任务

时间:2012-03-10 13:51:21

标签: java concurrency event-handling threadpool

我有许多优先级ABC的传入任务,我想在多核CPU上使用线程池处理任务。 70%的CPU应该用于处理'A}类任务,20%的CPU用于'B}类任务,10%的CPU用于'类型C'任务。

但是,如果只有“类型C”的任务到达,那么应该将100%的CPU用于它们。如果只有任务BC,那么66%会完成任务B和33%任务C等等......

您将如何在Java中实现它?

P.S: 优先级队列不起作用,因为那时只会处理任务类型。此外,为线程分配优先级不会起作用,因为它不准确。

6 个答案:

答案 0 :(得分:3)

也许你应该使用3个线程池。用于A任务的1个7个线程池,用于B任务的1个2个线程池,以及用于C任务的1个1个线程池。

编辑:即使只有C任务(或者,如果你有许多处理器,如果你只有B和C任务)也要具有并行性,将每个池中的线程数乘以处理器数,或者处理器数量+ 1,或者您喜欢的任何其他更大的因素。

答案 1 :(得分:0)

假设CPU上没有运行其他进程,则创建3个线程池,每个类型的任务一个,每个池的线程数与CPU上的核心数相同(这样整个CPU可以被任务使用)任何类型,如果只运行该类型的任务)。每个新任务都必须通过一段代码来记录每种类型的任务正在运行的数量。如果CPU上有可用核心,请立即启动新任务。如果没有空闲插槽,则从优先级低于新任务的优先级最低的池开始,并在必要时使用此扫描移动到下一个最高优先级池:中断/暂停正在运行的线程(假设任务设计为可中断/暂停)如果当前池超过其比例核心使用限制,则等待该任务完成(另一个任务可能先完成,这同样好)。在适当的池中启动新任务。如果无法启动新任务,它将在队列中等待另一个线程完成,从而释放新的插槽。当释放新的插槽时,刚刚完成的类型的任务获得释放的插槽的第一优先级,如果没有等待的任务,则启动具有最高优先级的等待任务。

答案 2 :(得分:0)

这实际上是一个相当困难的问题。基本上,您需要实现一个自定义阻止队列,该队列不仅可以跟踪挂起的作业,还可以当前正在运行的作业。对于待处理的作业,我会为各种优先级保留单独的列表。此外,您应该跟踪每个优先级的运行计数。当从队列中请求新作业时,您需要检查当前正在运行的作业的比率,并从最高适用的优先级中选择下一个可用作业(如果没有所需的优先级,则推迟到其他优先级)。很明显,您需要对正在运行的作业进行此队列的反馈,因此您可能希望用运行实际作业的包装器Runnable包装实际作业,然后在该作业完成时更新队列

答案 3 :(得分:0)

编写一个预测引擎,在统计上确定给定任务在更高优先级的任务到达之前完成的可能性。通过可接受的置信度值阈值进行参数化。所需置信度越高,您使用CPU的可能性就越大。阈值越低,越有可能为更低优先级的任务提供过多的CPU。

答案 4 :(得分:0)

由于这是一个采访问题,我只是建议如何解决问题的算法。

假设我们有三个独立的队列用于三种类型的任务,这意味着我们有三个队列,一个用于TypeA,另一个用于TypeB,其他用于Typec。

我们可以有一个queueToprocess让我们说它是Qp。

有一个调度程序可以监视Qa,Qb,Qc并填充Qp。

假设Qa,Qb,Qc中的每个任务都有一个特殊字段,表示完成任务所需的CPU周期数。

让我们说Qa有三个任务,第一个任务需要1个时钟周期,第二个任务需要3个时钟周期,第三个任务需要3个时钟周期。

让我们说Qb有一个任务需要2个时钟周期而Qc有一个任务需要1个时钟周期。

调度程序会将任务T拆分为小任务并在Qp中进行编程。

然后Qp看起来像Tc,Tb,Ta1,Ta2,Ta2,Ta2,Ta3,Ta3,Ta3。

处理器可以解除Qp并执行任务。

如果有人找到改进此算法的方法,请更正。

答案 5 :(得分:0)

这里真正需要的是一个实现共享的分层调度程序......您的层次结构如下所示:

           CPU
            |
-------------------------
|           |           |
A (70)     B (20)      C (10)
            |
       ---------------
       |  |  |  | |  | 
      T1 T2 T3 T4 T5 T6

请注意,我没有为A和C显示完整的层次结构,但我相信你明白了。现在要走的路是实现一个非常简单的基于虚拟时间的调度程序,让我们说Goyal的Start-Time Fair Queuing(SFQ)来处理A,B和C之间的调度。

这样的调度程序是保守的,这意味着如果只存在来自C的任务,则整个C将占用整个事物。

现在要处理第二级调度,你有两种方法...要么实现HSFQ,它是SFQ的分层版本,要么在A,B和C下面的线程中进行简单的循环,以便每个线程获得其池可用周期的“公平”份额。

我会小心使用循环法虽然公平性不是很好如果你有人口与突发线程和非常贪婪的线程混合...循环不会确保他们使用相同的周期数,除非你进入循环计数,这或多或少地归结为SFQ。

您还可以更具体地看看Stride Scheduling的分层版本......

希望它有所帮助,