生产者/消费者 - 使用高 CPU 的生产者

Posted

技术标签:

【中文标题】生产者/消费者 - 使用高 CPU 的生产者【英文标题】:Producer / Consumer - Producer using high CPU 【发布时间】:2014-02-26 19:39:08 【问题描述】:

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

简化:

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 使用率从 0% 攀升至极高 (13%)。

另外,如果我实例化该类的多个实例,每个实例的 CPU 使用率都会增加 13%。

大约每分钟左右(可能每 30 秒)将一个新的 LogItem 添加到 BlockingCollection,并将适用的消息写入文件。

是否有可能线程以某种方式阻塞了其他线程的运行,而系统需要以某种方式进行补偿?

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

【问题讨论】:

即使队列中没有任何内容,您发布的代码也会处理项目。 【参考方案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);
    

这也意味着,如果在阻塞部分的任何时候添加了一个项目,它会立即执行,而不是一秒钟后。

【讨论】:

是的,我确实注意到我的风扇打开得很快。添加 Thread.Sleep 方法是常见的解决方案吗?如果不是,您能否指出正确的做事方式? @TruthOf42:添加到答案

以上是关于生产者/消费者 - 使用高 CPU 的生产者的主要内容,如果未能解决你的问题,请参考以下文章

Java——多线程高并发系列之生产者-消费者模式

Java——多线程高并发系列之生产者-消费者模式

[Linux 高并发服务器]生产者与消费者模型

以非常高的速度将连续数据从服务发送到活动

生产者消费者模型,管道,进程之间共享内存,进程池

kafka生产者怎么样能够保障数据不丢,不重复且分区内数据有序!