生产者/消费者 - 生产者采用高CPU(Producer / Consumer - Producer

2019-10-19 10:53发布

我有一个以消费者为生产者消费者模式的一部分:

简化:

public class MessageFileLogger : ILogger
{
    private BlockingCollection<ILogItem> _messageQueue;
    private Thread _worker;
    private bool _enabled = false;
    public MessageFileLogger()
    {
         _worker = new Thread(LogMessage);
         _worker.IsBackground = true;
         _worker.Start();
    }

    private void LogMessage()
    {
        while (_enabled)
        {
            if (_messageQueue.Count > 0)
            {

                itm = _messageQueue.Take();
                processItem(itm);
            }
            else
            {
                Thread.Sleep(1000);
            }
        }
    }
}

如果我删除

Thread.Sleep(1000);

会导致CPU占用爬升的东西非常高(13%),而不是0%,与设置线程休眠。

此外,如果我实例化的类的多个实例,CPU使用率爬升在13%的增量,其中每个实例。

一个新的LogItem添加了BlockingCollection约每分钟左右(每30秒也许),以及在文件中写入适用的消息。

有没有可能是线程阻塞不知何故从运行其他线程,系统需要以某种方式来弥补?

更新:更新代码,以更好地反映实际的代码

Answer 1:

你给线程代码运行,因此默认情况下它尽可能快可能可以在一个单一的逻辑内核运行的代码(while循环)。 由于这是13%左右,我想像你的CPU有4个内核超线程,导致8个逻辑核心。 每个线程运行,这是while循环快,因为它可能会在它的核心,造成另外13%的使用率。 很简单真的。

不使用睡眠的副作用是使整个系统运行速度较慢,并且使用/产生显著多个电池/热量。

一般情况下,正确的方法是给_messageQueue像另一个方法

bool BlockingCollection::TryTake(type& item, std::chrono::milliseconds time)
{
    DWORD Ret = WaitForSingleObject(event, time.count());
    if (Ret)
        return false;
    item = Take(); //might need to use a shared function instead of calling direct
    return true;
}

然后,你的循环很简单:

private void LogMessage()
{
    type item;
    while (_enabled)
    {
        if (_messageQueue.Take(item, std::chrono::seconds(1)))
            ;//your origional code makes little sense, but this is roughly the same                
        processItem(itm);
    }
}

这也意味着,如果一个项目被阻隔部中的任何时候加入,它作用于而不是立即长达一整秒后。



文章来源: Producer / Consumer - Producer using high CPU