使工作线程等待任务的 CPU 效率最高的方法是啥?
Posted
技术标签:
【中文标题】使工作线程等待任务的 CPU 效率最高的方法是啥?【英文标题】:What is most CPU efficient method to make the worker threads wait for tasks?使工作线程等待任务的 CPU 效率最高的方法是什么? 【发布时间】:2011-01-04 23:30:57 【问题描述】:在我当前的 C#/NET 3.5 应用程序中,我有一个任务队列(线程安全),我有 5 个工作线程,它们必须不断地在队列中寻找任务。如果有任务可用,任何一个工作人员都会将该任务出列并采取必要的行动。
我的工作线程类如下:
public class WorkerThread
//ConcurrentQueue is my implementation of thread safe queue
//Essentially just a wrapper around Queue<T> with synchronization locks
readonly ConcurrentQueue<CheckPrimeTask> mQ;
readonly Thread mWorker;
bool mStop;
public WorkerThread (ConcurrentQueue<CheckPrimeTask> aQ)
mQ = aQ;
mWorker = new Thread (Work) IsBackground = true;
mStop = false;
private void Work ()
while (!mStop)
if (mQ.Count == 0)
Thread.Sleep (0);
continue;
var task = mQ.Dequeue ();
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;
task.IsPrime = IsPrime (task.Number);
task.ExecutedBy = Thread.CurrentThread.ManagedThreadId;
//Ask the threadpool to execute the task callback to
//notify completion
ThreadPool.QueueUserWorkItem (task.CallBack, task);
private bool IsPrime (int number)
int limit = Convert.ToInt32 (Math.Sqrt (number));
for (int i = 2; i <= limit; i++)
if (number % i == 0)
return false;
return true;
public void Start ()
mStop = false;
mWorker.Start ();
public void Stop ()
mStop = true;
问题是当队列为空时,它会消耗过多的 CPU(接近 98%)。我尝试了 AutoResetEvent 来通知工作人员队列已更改。因此,他们有效地等待该信号设置。它已将 CPU 降低到接近 0%,但我不完全确定这是否是最好的方法。您能否建议一种更好的方法来保持线程空闲而不损害 CPU 使用率?
【问题讨论】:
使用重置事件将是最好的方法。 另一种可能是使用 ThreadPool.QueueUserWorkItem 还有一个是使用计时器来检查队列并触发工作线程。 【参考方案1】:查看BlockingQueue 的这个实现。如果队列为空,它使用 Monitor.Wait() 使线程进入睡眠状态。添加项目时,它使用 Monitor.Pulse() 唤醒在空队列上休眠的线程。
另一种技术是使用semaphore。每次将项目添加到队列时,调用 Release()。当您需要队列中的项目时,请调用 WaitOne()。
【讨论】:
我喜欢 Semaphore 的想法,因为它确保如果将一项添加到队列中,则仅唤醒一个线程。使用重置事件唤醒所有工作线程。谢谢。 但是它有一个downsite,我必须在我创建信号量时指定队列中允许的最大项目数!信号量的效率是否足以处理非常大的计数? 回应第一条评论。 Monitor.Pulse 只唤醒一个线程(Monitor.PulseAll)会唤醒每个线程,所以没有区别。 只要设置最大可能的值。new Semaphore(0, Int32.MaxValue)
郑重声明:我使用了信号量技术,效果很好!谢谢大家。【参考方案2】:
您当前的工作方法中有Thread.Sleep(0)
,用于没有队列项。将其更改为 anything 大于 0,您的 CPU 使用率就会下降。尝试10
开头...
【讨论】:
【参考方案3】:你有几个我能想到的选择。
一种方法是在循环期间放置一个小线程睡眠。这基本上会将您的 CPU 使用率降至 0,这是相当标准的做法。
另一种方法是按照 Mitch Wheat 在 cmets 中的建议使用重置(自动或手动)。
您还可以设计某种 IdleTask,让线程休眠一段时间,如果您的队列为空,只需处理 IdleTask(它将线程休眠)。
【讨论】:
【参考方案4】:如果您的队列是线程安全的,那么您就不需要这样做...
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;
【讨论】:
以上是关于使工作线程等待任务的 CPU 效率最高的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章