C++ queue使用原理介绍以及在多线程的应用

1 queue原理

1.1 queue简述

        std::queue: 模板类queue定义在<queue>头文件中。队列(Queue)是一个容器适配器(Container adaptor)类型,被特别设计用来运行于FIFO(First-in first-out)场景,在该场景中,只能从容器一端添加(Insert)元素,而在另一端提取(Extract)元素。只能从容器”后面”压进(Push)元素,从容器”前面”提取(Pop)元素。用来实现队列的底层容器必须满足顺序容器的所有必要条件。

       queue模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque类型。

                    图一

 

1.2 queue的API

queue 模板类的定义在<queue>头文件中。

与stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类

型,元素类型是必要的,容器类型是可选的,默认为deque 类型。

定义queue 对象的示例代码如下:

queue<int> q1;

queue<double> q2;

queue 的基本操作有:

入队,如例:q.push(x); 将x 接到队列的末端。

出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。

访问队首元素,如例:q.front(),即最早被压入队列的元素。

访问队尾元素,如例:q.back(),即最后被压入队列的元素。

判断队列空,如例:q.empty(),当队列空时,返回true。

访问队列中的元素个数,如例:q.size()

在上图一队列中,只能通过q.front()和q.back()访问a0和an,要想访问a1,必须调用q.pop(),将a0弹出队列,在调用q.front()进行访问。

1.3 代码实例1

#include <cstdlib>

#include <iostream>

#include <queue>

using namespace std;

int main()

{

    int e,n,m;

    queue<int> q1;

    for(int i=0;i<10;i++)

       q1.push(i);

    if(q1.empty())

    cout<<"queue is empty.\n";

    n=q1.size();

    cout<<n<<endl;

    m=q1.back();

    cout<<m<<endl;

    for(int j=0;j<n;j++)

    {

       e=q1.front();

       cout<<e<<" ";

       q1.pop();

    }

    cout<<endl;

    if(q1.empty())

    cout<<"queue is empty.\n";

    return 0;

}

10

9

0 1 2 3 4 5 6 7 8 9

queue is empty.

1.4 代码实例2-string

{ // std::queue::emplace: C++11, Construct and insert element.
  // Adds a new element at the end of the queue, after its current last element.
  // The element is constructed in-place, i.e. no copy or move operations are performed.
  // queue::push: inserts element at the end , queue::emplace: constructs element in-place at the end
  // queue::pop: removes the first element 
	
    std::queue<std::string> myqueue;
 
	myqueue.emplace("First sentence");
	myqueue.emplace("Second sentence");
 
	std::cout << "myqueue contains:\n";
	while (!myqueue.empty()) {
		std::cout << myqueue.front() << '\n';
		myqueue.pop();
}

 

2 queue在多线程中应用

通过使用消息队列queue,可以实现多线程通信。以及一个线程频繁接收到消息,而已处理这个消息,需要耗费一点时间,处理消息阻塞当前线程,导致无法接到到新的消息,造成异常。因此额外开一个新的线程,此新线程只管处理消息,当前线程只管接收消息,接收后当前函数退出,处理其他任务,即可避免阻塞线程了。实现系统的稳定。

在处理为了避免数据冲突,需要用到锁和条件锁。

2.1 代码实例

static pthread_mutex_t onLock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t  onCond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t onMutex = PTHREAD_MUTEX_INITIALIZER;

std::queue<std::string> onMessageQueue;

//额外启动一个消息执行队列
void AppManager::starMessageThread(){
    pthread_t id;
    int ret = pthread_create(&id, NULL, (void *) onMessageExecuteThread, NULL);
    pthread_detach(id);
    if (ret != 0) {
        APP_INFO("startProcessThread create pthread fail");
    }
}
//消息处理线程,无消息时,进入休眠状态,不占用资源
static void * AppManager::onMessageExecuteThread()
{
    prctl(PR_SET_NAME, (unsigned long)"onMessageExecuteThread");

    while(1)
    {

        pthread_mutex_lock(&onLock);
        pthread_cond_wait(&onCond, &onLock);//阻塞,等待条件
        pthread_mutex_unlock(&onLock);

        while(onMessageQueue.size() > 0)//处理完所有消息
        {
            pthread_mutex_lock(&onMutex);
            std::string message = onMessageQueue.front();
            onMessageQueue.pop();
            pthread_mutex_unlock (&onMutex);

            onProcessMessage(message); //实际的消息处理函数,这样与发送消息的线程分开,避免占用发送消息线程的时间
        }
    }

    return NULL;
}

//另一个线程的回调函数,通过这个函数发送消息

bool AppManager::onSendMessage(const std::string &message) {
    
    pthread_mutex_lock (&onMutex);
    onMessageQueue.push(message);
    pthread_mutex_unlock (&onMutex);

    pthread_mutex_lock (&onLock);
    pthread_cond_signal(&onCond);
    pthread_mutex_unlock (&onLock);

    return true;
}

 

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值