当前位置: 首页 > 知识库问答 >
问题:

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

艾阳羽
2023-03-14

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

简化:

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%的增量攀升。

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

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

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

共有1个答案

韩阳云
2023-03-14

您让线程代码运行,因此默认情况下,它在单个逻辑核心上尽可能快地运行该代码(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);
    }
}

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

 类似资料:
  • 本教程演示了如何发送和接收来自Spring Kafka的消息。 首先创建一个能够发送消息给Kafka主题的Spring Kafka Producer。 接下来,我们创建一个Spring Kafka Consumer,它可以收听发送给Kafka主题的消息。使用适当的键/值序列化器和解串器来配置它们。 最后用一个简单的Spring Boot应用程序演示应用程序。 下载并安装Apache Kafka 要

  • 生产者线程与消费者线程使用信号量同步 生产者线程与消费者线程使用信号量同步 源码/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-08-24 yangjie the f

  • 所谓的生产者消费者模型就是 某个模块(函数)负责生产数据,这些数据由另一个模块来负责处理 一般生产者消费者模型包含三个部分 生产者、缓冲区、消费者 为什么生产者消费者模型要含三个部分?直接生产和消费不行么? 一个案例说明一切 生产者好比现实生活中的某个人 缓冲区好比现实生活中的邮箱 消费者好比现实生活中的邮递员 如果只有生产者和消费者, 那么相当于只有写信的人和邮递员,那么如果将来过去的邮递员离职

  • 一、线程间通信的两种方式 1.wait()/notify() Object类中相关的方法有notify方法和wait方法。因为wait和notify方法定义在Object类中,因此会被所有的类所继承。这些方法都是final的,即它们都是不能被重写的,不能通过子类覆写去改变它们的行为。 ①wait()方法: 让当前线程进入等待,并释放锁。 ②wait(long)方法: 让当前线程进入等待,并释放锁,

  • 我有一个生产者/消费者模式,如下所示 固定数量的生成器线程,每个线程写入它们自己的BlockingQueue,通过执行器调用 单个使用者线程,读取生产者线程 每个生产者都在运行一个数据库查询,并将结果写入其队列。消费者轮询所有生产者队列。目前,如果出现数据库错误,生产者线程就会死掉,然后消费者就会永远停留在产品队列中等待更多的结果。 我应该如何构造它来正确处理catch错误?

  • 问题内容: 我对于如何使用特定的生产者-消费者模式感到困惑,在该模式中,生产者和消费者都可以同时并独立地进行操作。 首先,考虑以下示例,该示例紧随docs中的示例: 关于此脚本,有一个更详细的细节:通过常规的for循环将项目同步放入队列。 我的目标是创建一个使用(或)和的脚本。两者都应安排为同时运行。没有一个消费者协程明确地与生产者绑定或链接。 我如何修改上面的程序,以便生产者是可以与消费者/工人