在我当前的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使用率?
4 回答
看看BlockingQueue的这个实现 . 如果队列为空,则使用Monitor.Wait()将线程置于休眠状态 . 添加项目时,它使用Monitor.Pulse()来唤醒正在空队列中休眠的线程 .
另一种技术是使用semaphore . 每次将项添加到队列时,请调用Release() . 如果需要队列中的项目,请调用WaitOne() .
您当前在Work方法中有
Thread.Sleep(0)
,其中没有队列项 . 将其更改为大于0的任何值,您的CPU使用率将下降 . 试试10
开头......你有几个我能想到的选择 .
一种方法是在循环期间放置一个小线程休眠 . 这将基本上将您的CPU使用率降低到0,这是相当标准的方法 .
另一种方法是在评论中使用Mitch Wheat建议的重置(自动或手动) .
您还可以设计一些线程休眠一段时间的IdleTask,如果您的队列为空,只需处理IdleTask(将线程休眠) .
如果您的队列是线程安全的,那么您不需要这样做......