首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

用C++构建多线程工作队列(使用者/生产者)

在云计算领域,构建多线程工作队列的方法有很多种。以下是一个简单的示例,使用 C++ 11 标准库中的线程和队列容器实现一个多线程生产者-消费者模式。

首先,我们需要包含必要的头文件和命名空间:

代码语言:cpp
复制
#include<iostream>
#include<queue>
#include<thread>
#include <mutex>
#include<condition_variable>
#include<vector>
#include<chrono>
#include<atomic>

接下来,我们定义一个工作队列类,其中包含一个任务队列、一个互斥量、一个条件变量和一个原子布尔变量:

代码语言:cpp
复制
class WorkQueue {
public:
    WorkQueue() : stop(false) {}

    void push_task(int task) {
        std::unique_lock<std::mutex> lock(mutex);
        tasks.push(task);
        cv.notify_one();
    }

    bool pop_task(int& task) {
        std::unique_lock<std::mutex> lock(mutex);
        cv.wait(lock, [this] { return !tasks.empty() || stop; });
        if (tasks.empty()) return false;
        task = tasks.front();
        tasks.pop();
        return true;
    }

    void stop_queue() {
        stop.store(true);
        cv.notify_all();
    }

private:
    std::queue<int> tasks;
    std::mutex mutex;
    std::condition_variable cv;
    std::atomic<bool> stop;
};

然后,我们定义一个生产者线程函数,用于向工作队列中添加任务:

代码语言:cpp
复制
void producer(WorkQueue& queue, int num_tasks) {
    for (int i = 0; i < num_tasks; ++i) {
        queue.push_task(i);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    queue.stop_queue();
}

接下来,我们定义一个消费者线程函数,用于从工作队列中获取任务并处理:

代码语言:cpp
复制
void consumer(WorkQueue& queue) {
    int task;
    while (queue.pop_task(task)) {
        std::cout << "Consumer processing task: "<< task<< std::endl;
    }
}

最后,我们在主函数中创建生产者和消费者线程,并等待它们完成:

代码语言:cpp
复制
int main() {
    WorkQueue queue;
    int num_tasks = 10;

    std::thread producer_thread(producer, std::ref(queue), num_tasks);
    std::thread consumer_thread(consumer, std::ref(queue));

    producer_thread.join();
    consumer_thread.join();

    return 0;
}

这个示例展示了如何使用 C++ 11 标准库中的线程和队列容器实现一个多线程生产者-消费者模式。当然,在实际应用中,您可能需要根据具体需求对其进行调整和优化。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++并发编程之玩转condition_variable

C++并发编程之玩转condition_variable 0.导语 最近在看并发编程相关的代码,自己顺手从0开始写了个小项目玩转并发场景下的生产消费者模型,如果你想提高多线程编程方面的能力,想熟练掌握...可以通过调用回调函数来停止生产者和消费者的处理,并进行清理工作 通过这几个版本的学习可以掌握: 1.多线程和并发编程:通过这些版本的描述,您可以了解到如何在C++中使用多线程和并发编程来处理并行任务。...4.代码组织和构建工具:提到了支持bazel编译的能力,这可以让您学习如何使用构建工具来组织和管理复杂的C++项目。...此时需要引入队列,我们将任务丢到队列中去,随后多个消费者进行消费即可,与上述等待条件不同点在于队列的状态。...对于生产者:如果队列大小未达到 max_queue_size_ 的限制,如果队列已满,则生产者线程将等待消费者线程从队列中取走一些数据。

22230

C++任务队列多线程

摘要:       很多场合之所以使用C++,一方面是由于C++编译后的native code的高效性能,另一方面是由于C++优秀的并发能力。...任务队列的实现: 任务的定义       生产者消费者模型在软件设计中是极其常见的模型,常常被用来实现对各个组件或系统解耦合。...大到分布式的系统交互,小到网络层对象和应用层对象的通讯,都会应用到生产者消费者模型,在任务队列中,生产和消费的对象为“任务”。...任务队列的close接口是专门用来停止任务队列工作的,代码如下: void close() { lock_guard_t lock(m_mutex); m_flag...Socket自己本身可以保存对应任务队列的引用,这样使用者只需调用socket的接口,而接口内部再将请求投递到争取的任务队列

2.8K40
  • UE4的队列TQueue

    TQueue是UE4提供的队列容器,完全满足队列的先进先出性质,这里主要用于多线程同步数据。...如果比较了解多线程编程的话,那你肯定知道多线程中最常用的一个容器就是消息队列,解决的就是生产者-消费者问题。...如果经常写C++的话,肯定会想到STL中的队列std::queue,std的队列底层其实是std::deque这个容器来实现的,内部存储是通过链表+数组的形式,把不同的块链在一起,我们知道std::vector...进队列Enqueue: 代码里的TSAN系列宏可以先无视,是查高并发时数据竞争的BUG的,有兴趣可以看这篇怎么。...对于单生产者来说,即使不是线程安全的,但是因为只有一个生产者,不会出现多线程同时修改Head这样的操作,所以也是没有问题的。

    3K30

    线程之生产者消费者模式

    这篇是第五篇生产者消费者模式在我们日常工作中用得非常多,比如:在模块解耦、消息队列、分布式场景中都很常见。...生产者不用管消费者的动作,消费者也不用管生产者的动作;它两之间就是通过阻塞队列通信,实现了解耦;阻塞队列的加入,平衡二者能力;生产者只有在队列满或消费者只有在队列空时才会等待,其他时间谁抢到锁谁工作,提高效率...这就是所谓的等待唤醒机制 先来看看等待唤醒机制如何实现生产者、消费者模式的,首先是阻塞队列: public class MyBlockingQueue { private int maxSize...因为我们的生产者和消费者线程都只有一个,但是多线程情况下 if 就大错特错了。想象以下情况: 1、假设有两个消费者一个生产者队列为空,消费者一进入等待状态,释放锁。...但其实背后 ArrayBlockingQueue 已经为我们做好了线程间通信的工作了,比如队列满了就去阻塞生产者线程,队列有空就去唤醒生产者线程等。

    93320

    RabbitMQ 入门案例

    # RabbitMQ 入门案例 Hello RabbitMQ 添加依赖 消息生产者 消息消费者 Work Queues 轮询消费 轮询案例 Web页面添加队列 # Hello RabbitMQ Java...中间的框是一个队列 RabbitMQ 代表使用者保留的消息缓冲区 注意 Java 进行连接的时候,需要 Linux 开放 5672 端口,否则会连接超时 访问 Web 界面的端口是 15672,连接服务器的端口是...案例中生产者叫做 Task,一个消费者就是一个工作队列,启动两个工作队列消费消息,这个两个工作队列会以轮询的方式消费消息。...,只需要以多线程方式启动两次该 main 函数即可,以 first、second 区别消息队列。...要开启多线程功能,首先启动该消息队列,然后如图开启多线程: 两个工作队列都启动后 创建一个生产者,发送消息进程 /** * @author frx * @version 1.0 * @date

    41030

    MQ界的“三兄弟”:Kafka、ZeroMQ和RabbitMQ,有何区别?该如何选择?

    工作流程如下:生产者将消息发送到指定的队列队列存储消息,直到有一个消费者从队列中获取它。一个消费者获取队列中的消息并进行处理。...工作流程如下:生产者将消息发送到交换器,并指定一个路由键。交换器根据路由键将消息路由到匹配的队列队列存储消息,等待消费者获取并处理它。...这种模式适用于需要根据灵活的条件将消息路由到不同队列的场景。工作流程如下:生产者将消息发送到交换器,并指定一个主题匹配规则。交换器根据主题匹配规则将消息路由到匹配的队列。...这种模式适用于需要在多个消费者之间分配负载的场景,例如任务队列或并行处理。图片工作流程如下:生产者将消息发送到共享队列。多个消费者竞争性地获取队列中的消息。每个消费者独立地处理它获取的消息。...3.4.3 多线程并发模式ZeroMQ 提供了多线程并发模式,允许多个线程通过套接字进行消息通信。这种模式可以用于多线程环境中的并发编程。工作流程如下:多个线程创建套接字,并绑定或连接到相应的地址。

    9.3K32

    消息队列生产者消费者模式

    消费者在获取数据时候有可能一次不能处理完,那么它们各自有一个请求队列,那就是内存缓冲区了。做这项工作的框架叫做消息队列。...3.生产者消费者模型的实现   生产者是一堆线程,消费者是另一堆线程,内存缓冲区可以使用List数组队列,数据类型只需要定义一个简单的类就好。关键是如何处理多线程之间的协作。...好在前人已经做了大量的工作,可借助于这些第三方的库和框架,比如C++的ACE库、Python的Twisted。...队列为空的时候,读出端无法读取数据;当队列满(达到最大尺寸)时,写入端无法写入数据。 对于使用者来讲,环形缓冲区和队列缓冲区是一样的。...所以,从队列缓冲区切换到环形缓冲区,对于使用者来说能比较平滑地过渡。 2.内部结构迥异 虽然两者的对外接口差不多,但是内部结构和运作机制有很大差别。

    1.9K31

    Java高并发之BlockingQueue

    简介 多线程中通过队列很容易共享数据,比如经典的生产者和消费者模型中,通过队列可以很方便的实现数据共享。假设我们有若干生产者线程,又有若干消费者线程,生产者线程可以通过队列将数据共享给消费者。...concurrent出来之后,带来了BlockingQueue(在多线程中,在某些情况下挂起线程(即阻塞),一旦条件满足,被挂起的线程又会被自动唤醒) [这里写图片描述] BlockingQueue即为阻塞队列...当一个线程试图对一个为空的队列进行出队列操作时,也将会被阻塞,除非有一个线程进行了出队列操作。 阻塞队列是线程安全的,主要用在生产者消费者的场景上。...所以如果允许插入null值的话,那获取的时候,就不能很好的null来判断到底是失败还是获取的值为null。...作为BlockingQueue的使用者,我们再不用考虑何时阻塞线程,什么时候唤醒线程,因为这一些BlockingQueue都实现了。

    49400

    C++11多线程编程(五)——生产消费者模型之条件变量

    在生产消费者模型当中,肯定都会用到互斥锁的机制的,当生产者队列中放数据的瞬间,消费者是不能取数据的,那这时候可能会碰见一个问题,如果生成者因为某些原因,放数据过慢,但是消费者取数据很快,当队列中没有数据了...这时候我们设想,能否设计这样的一种机制,如果在队列没有数据的时候,消费者线程能一直阻塞在那里,等待着别人给它唤醒,在生产者队列中放入数据的时候通知一下这个等待线程,唤醒它,告诉它可以来取数据了。...于是多线程中的条件变量就横空出世! 条件变量是多线程数据同步的一种操作,不管是哪种框架,哪种语言实现多线程的功能,条件变量都是不得不考虑的一种情况。...C++中提供了#include 头文件,里面就包含了条件变量的相关类。...:首先生产者利用unique_lock来加锁,然后将生产的数据放入队列,打印,解锁,一旦解锁之后,消费者获得了执行机会。

    27010

    Python学习—python中的线程

    就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。...理论上多线程执行任务, 会产生一些数据, 为其他程序执行作铺垫; 2). 多线程是不能返回任务执行结果的, 因此需要一个容器来存储多线程产生的数据 3). 这个容器如何选择?...list(栈, 队列), tuple(x), set(x), dict(x), 此处选择队列来实现 队列多线程 import threading from queue import Queue def...2.并发 由于生产者与消费者是两个独立的并发体,他们之间是缓冲区通信的,生产者只需要往缓冲区里丢数据,就可以继续生产下一个数据,而消费者只需要从缓冲区拿数据即可,这样就不会因为彼此的处理速度而发生阻塞...__init__() self.q = q def run(self): # 阻塞0.001妙使生产者先运行再队列中放入数据 time.sleep

    4.2K10

    C++11多线程编程(六)——线程池的实现

    多线程编程的好好的,干嘛还要引入线程池这个东西呢?引入一个新的技术肯定不是为了装逼,肯定是为了解决某个问题的,而服务端一般都是效率问题。...我们可以看到多线程提高了CPU的使用率和程序的工作效率,但是如果有大量的线程,就会影响性能,因为要大量的创建与销毁,因为CPU需要在它们之间切换。...二、C++中的线程池 但是让人遗憾的是,C++并没有在语言级别上支持线程池技术,总感觉C++委员会对多线程的支持像是犹抱琵琶半遮面的羞羞女一样,无法完全的放开。...,放入之后在解锁,这里的加锁解锁可以unique_lock结构,当然也可以mutex结构,而放入任务队列之后就可以条件变量的notify_one函数通知阻塞的线程来取任务处理了。...看过我之前写的《生产消费者模型之条件变量》的朋友对以上代码有点熟悉,没错,线程池的实现就有点像是生产消费者模型,append()就像是生产者,不断的将任务放入队列,run()函数就像消费者,不断的从任务队列中取出任务来处理

    31610

    3分钟速读原著《Java并发编程的艺术》(三)

    2.1 AbstractQueuedSynchronizer (队列同步器),是用来构建锁和其他同步组件的基础框架,使用int成员变量来表示同步状态,内置的FIFO队列来完成资源获取线程的同步工作 2.2...队列会阻塞读取元素的线程,直到队列不为null 3.3 阻塞队列的模型类似于生产者和消费者的模型 ①一直阻塞:当阻塞队列满时,如果生产者线程往队列里面put元素,队列会一直阻塞生产者线程,直到队列可以或者响应中断退出...,当队列空时,如果消费者线程从队列中获取元素,队列会阻塞消费者线程,直到队列不为空 ②超时退出:当阻塞队列满时,如果生产者线程往队列里面插入元素,队列会阻塞生产者线程一段实际,如果超过了指定的时间,生产者线程就会退出...,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列尾部拿任务执行 4.2 工作窃取算法的优点:充分利用线程进行并行计算,减少了线程之间的竞争 4.3 工作窃取算法的缺点:在某些情况下仍然存在竞争...,进入队列的头部.当一个工作线程当中暂时没有任务时,它会随机从其他工作线程的队列尾部获取一个任务 6.Fork/Join框架的实现原理 6.1 当我们调用ForkJoinTask的fork方法时,程序会调用

    29310

    Java synchronized 使用

    生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。...关于JAVA多线程同步 JAVA多线程同步主要依赖于若干方法和关键字 1  wait方法: 该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用...但是c和c++中并不如此。 第一点:对引用变量和除了long和double之外的原始数据类型变量进行读写。 第二点:对所有声明为volatile的变量(包括long和double)的读写。...为了能使不同的进程互相访问资源并进行协调工作,才有了进程间通信。这些进程可以运行在同一计算机上或网络连接的不同计算机上。 进程间通信技术包括消息传递、同步、共享内存和远程过程调用。...(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。

    58920

    C++多线程编程课程

    本专栏将从操作系统原理的角度介绍多线程技术的方方面面,从基础的知识到高级进阶,它们是笔者这些年工作的经验总结和踩坑之后的教训。 本专栏的内容主要分为以下三大方面。...API 从而深入理解操作系统的工作原理,这本身就有很重要的意义。...如何让一个程序只允许使用者运行一个实例? 在实际开发中,避免死锁有哪些可以遵循的规则? 什么是条件变量的虚假唤醒?虚假唤醒会带来什么问题?如何解决? 如何设计高效的线程池和队列模型?...好在,C++ 11/14 标准给 C++ 引入了大量的多线程类和库,本专栏也会详尽地介绍它们的用法。 以下是专栏的主要内容导图: ?...这是在学习和开发多线程程序时不得不面临的问题。 只要透彻地理解了这些操作系统提供的基础多线程同步原语,在面对它们的衍生物(如线程池、消息队列、协程技术等)时可以更快地学习和用好。

    1.2K30

    【Redis】初识 Redis

    ,除了新浪微博,还有像阿里巴巴、腾讯、搜狐、优酷土豆、美团、小米、唯品会等公司都是 Redis 的使用者。...Redis 是 C 语言实现的,一般来说 C语言 实现的程序 “距离” 操作系统更近,执行速度相对会更快。...3.1 实时数据存储 Redis 的多种内存数据结构可以为需要低延迟和高吞吐量的实时应用程序构建数据基础设施,即 Redis 可以作为数据库。...消息队列系统可以说是⼀个大型网站的必备基础组件,通过它我们可以实现一个网络版本的生产者消费者模型,从而在分布式系统中做到业务解耦与非实时业务削峰等工作。...设置工作目录 先先创建工作目录: mkdir -p /var/lib/redis 再在 /etc/redis.conf 配置文件中,设置 Redis 工作目录: dir /var/lib/redis

    18210

    BlockingQueue

    通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。...多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。假设我们有若干生产者线程,另外又有若干个消费者线程。...如上图所示:当队列中填满数据的情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有空的位置,线程被自动唤醒。 这也是我们在多线程环境下,为什么需要BlockingQueue的原因。...作为BlockingQueue的使用者,我们再也不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给你一手包办了。...ArrayBlockingQueue和LinkedBlockingQueue是两个最普通也是最常用的阻塞队列,一般情况下,在处理多线程间的生产者消费者问题,使用这两个类足以。 3.

    52170

    Python 多线程入门,这一篇文章就够了

    Python 和多线程 提及 Python 啊,我想你首先想到的就是「人生苦短,我 Python」了。...关于多线程啊,我想你肯定不陌生,无论是高级语言的鼻祖 C 语言、还是 C++、Java,都支持多线程、多进程,而且这部分知识无论是在求职面试还是在日常的工作开发中,都会涉及到,不巧的是呢,这部分知识在老师讲课过程中是很少涉及的...比较正式的话来说,进程就是处于运行中的程序,并且具有一定独立的功能。进程是操作系统进行资源分配和调度的一个独立单位。...生产者、消费者模型 提到多线程,最著名的就是生产者、消费者模型了,那应该如何实现呢? 说实话,我当初最开始学习生产者、消费者模型的时候,心里是有点犯嘀咕的,感觉涉及到线程间的通信,太好解决。...只不过有时候会出现特殊的情况 队列空了,消费者还要消费数据 队列满了,生产者还要生产数据 这是我们需要重点考虑了,解决了以上两点,这个模型也就实现了。 接下来我们就来看看 Python 如何实现吧!

    58440

    无锁队列的几种实现及其性能对比

    但是如果一秒只需要处理几百或者几千的数据,是没有必要考虑无锁队列的。互斥锁就能解决问题,数据量相对少的时候互斥锁与无锁队列之间差别并不是很明显。 二、为什么要用无锁队列? 有锁队列会有哪些问题?...ypipe 是在 yqueue_t 的基础上再构建一个单读单写的无锁队列。...以上三种不同的下标都是必须的,因为队列允许任意数量的生产者和消费者围绕着它工作。已经存在一种基于循环数组的无锁队列,使得唯一的生产者和唯一的消费者可以良好的工作。它的实现相当简洁非常值得阅读。...这也就是为什么我把是否启用此成员变量的选择交给实际的使用者.使用者可以根据自己的使用场合选择是否承受额外的运行时开销。...,但偶尔会有其它生产者队列 push 数据; 在 reactor 网络框架中,如果只有一个 reactor 在处理 client 的话,数组实现的 RingBuffer 来存储消息是比较合适的。

    6K21

    Java并发基础:ArrayBlockingQueue全面解析!

    内容摘要ArrayBlockingQueue类是一个高效、线程安全的队列实现,它基于数组,提供了快速的元素访问,并支持多线程间的同步操作,作为有界队列,它能有效防止内存溢出,并通过阻塞机制平衡生产者和消费者的速度差异...比如,厨房的每个工作台都有一定的处理能力,比如同时只能处理5个订单,超过这个数量,工作台就会变得拥挤而无法再接单,为了模拟这种有限的处理能力,可以创建一个容量为5的ArrayBlockingQueue。...,则表示当前厨房工作台负荷过大,订单处理器线程会进入等待状态,直到厨房完成了一个订单并将结果从队列中取出后,新订单才有机会被加入队列。...主要功能ArrayBlockingQueue主要用于解决以下功能问题:**多线程间的数据共享**: 在多线程编程中,线程之间经常需要共享数据ArrayBlockingQueue作为一个线程安全的队列...核心总结ArrayBlockingQueue是一个非常实用的有界阻塞队列,其优点在于,基于数组实现,内存占用连续,查询速度快;同时支持多线程间的同步操作,能够很好地处理生产者-消费者问题。

    23300

    新版 Tokio 调度器性能提升10倍

    调度器的优化围绕以下几个方面展开: 新的 std::future 任务系统 更好的队列算法 优化消息传递模式 改进的“任务窃取”算法 减少跨线程同步 减少内存分配 减少原子的引用计数 1 调度器如何工作...单队列+多处理器 优点:实现简单;任务被公平调度。 缺点:所有处理器守着队头,真正执行任务消耗的时间远大于任务从队列中弹出的时间。rust 的异步任务是短耗时的,争队列的开销大。...更好的任务队列 对每个队列使用固定大小。当队列已满时,任务将被推送到一个全局的、多使用者、多生产者队列中。处理器需检查该全局队列,但频率比本地队列低得多。 优点:避免了扩容本地队列带来的开销。...双端队列的扩容较为负载。 细节:本地队列使用一个固定大小的单生产者、多消费者队列,只需要很少的同步便可正常工作。...Loom 会运行多次例,同时会枚举在多线程环境下可能遇到的行为,并验证内存访问、内存分配和释放是否正确。 参考 https://tokio.rs/blog/2019-10-scheduler

    98310
    领券