首页 > 解决方案 > 在某些情况下使用阻塞处理从队列中消耗元素

问题描述

我有一个推送到队列的线程和一个消耗队列中元素的线程。其中一个元素的处理是异步的,但我不想在这个处理过程中处理其他元素。(假设输出流和队列是线程安全的)

我想知道实现消费线程的最佳方法是什么……我认为 while(true) 和条件不是最佳选择。

它是简单的实现吗(process2必须是异步的)。

#include <iostream>
#include <queue>
#include <thread>
#include <atomic>
#include <future>

std::atomic_bool isProcess2Processing{false};

void process0()
{
    std::cout << "process0" << std::endl;
}

void process1()
{
    std::cout << "process1" << std::endl;
}

void process2()
{
    std::async(std::launch::async, []() { isProcess2Processing = true; std::cout << "start process2" << std::endl; while (std::rand() > 10000) {}; std::cout << "finished proces2" << std::endl; isProcess2Processing = false; });
}

void consume(int x)
{
    if (x == 0)
    {
        process0();
    }
    else if (x == 1)
    {
        process1();
    }
    else
    {
        process2();
    }
}

int main()
{
    std::queue<int> q;

    std::thread consumingThread([&q]() {
        while (true) {
            if (!q.empty() && !isProcess2Processing) {
                consume(q.front());
                q.pop();
            }
        }
    });

    while (true)
    {
        q.push(std::rand() % 3);
    }
}

标签: c++multithreadingasynchronousqueuec++14

解决方案


我想知道实现消费线程的最佳方法是什么……我认为 while(true) 和条件不是最佳选择。

您在这里的考虑是有道理的:使用这样的 while 循环(即不涉及任何等待)的最大问题是您在浪费 CPU 时间和功率。您的辅助线程(以及根据您的主线程给出的代码)在一段时间内无缘无故地将 CPU 内核全部保留给自己,因此其他任务无法为自己获得 CPU 时间。

进行更改的最天真的方法是在此处添加某种类似的内容sleep

std::thread consumingThread([&q]() {
    while (true) {
        if (!q.empty() && !isProcess2Processing) {
            consume(q.front());
            q.pop();
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
    }
});

在这里,您将休眠 5 毫秒,在此期间调度程序将能够让其他任务完成它们的工作。

此外,您应该确保有一些事情是每个循环的退出条件,并consumingThread.join();在您离开之前调用main()


推荐阅读