1.队列的介绍队列是C/C中最基础的数据结构之一队列本质上是一种线性表。它遵循着先进先出(fifo)的特点在队列中一般在队尾插入队头出队。这就相当于排队一样刚入队的人需要排在队尾(rear)每次出队的都是在队首(front)。在实际开发中队列发挥着巨大的作用比方说多线程数据传输、缓存数据的存储、中间件的设计等等。从上面这张图我们可以看到队尾入队了三个元素分别是1,2,3。1号数据最早入队、2号数据第二入队、3号数据最后入队。出队的时候1号最早出队(pop1)、2号排在1号数据后面(pop2)、3号最后出队(pop3)。所以使用队列的时候我们可以保证数据的顺序不会出现乱序的错误。2.队列的用处队列常用于在多线程数据传输、数据解耦、缓存数据等方面。由于在大型的项目开发中往往有许多线程同时运作。此时许多线程之间需要进行数据的传递所以此时我们就需要通过队列作为一条桥梁把数据从一个线程送到另外一个线程里面(如下图一就是队列在两个线程之间的通信)。线程一把数据按照顺序把数据包存储到Queue上、线程二、三也按照顺序从队列拿到数据。图一除了线程之间通信之外队列还常用于数据量缓存方面。比方说在音视频解码的时候音视频数据会大量传入解码端。假设此时没有一个缓冲的时间解码端可能会因为处理速度的问题导致解码视频的时候会出现花屏、卡顿等问题。所以此时我们就需要用队列进行缓冲使其传输速度降下来那解码端的解码压力就会大大降下来此时解码出来的画面质量就会高很多具体的流程如图二。(图二)3.C STL队列的用法C库已经提供了一套队列的api方便开发者进行开发这样我们就不用重新再新造轮子去实现队列。下面我们就来看看我们用stl queue去实现队列3.1. queue的初始化#include queuestd::queueobject object_queue;初始化stl的queue需要做两步。第一步要包含queue头文件#includequeue第二步声明queuestd::queueobject object_queue。这里的object里面的object是任意类型的数据也包括结构体的数据。3.2.queue的操作apifront()返回 queue 中第一个元素的引用。如果 queue 是常量就返回一个常引用如果 queue 为空返回值是未定义的。back()返回 queue 中最后一个元素的引用。如果 queue 是常量就返回一个常引用如果 queue 为空返回值是未定义的。push(const T obj)在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back() 来完成的。push(T obj)以移动的方式在 queue 的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数 push_back() 来完成的。pop()删除 queue 中的第一个元素。size()返回 queue 中元素的个数。empty()如果 queue 中没有元素的话返回 true。emplace()用传给 emplace() 的参数调用 T 的构造函数在 queue 的尾部生成对象。swap(queueT other_q)将当前 queue 中的元素和参数 queue 中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。3.3.queue的demo上面这个是一个简单的stl queue操作先入队6个元素(0-5)。然后再连续出队pop这里总共出队了4次此时元素0 1 2 3全部出队并删除所以打印front的元素是4。4.C多线程队列的框图上图是同一个典型的多线程入队出队的过程。这里需要创建两个线程一个是入队线程、一个是出队线程。入队线程主要是通过push的api向Queue的队尾插入数据插入数据的同时通过pthread_cond_broadcast通知出队线程取出数据。此时出队线程正在等待入队线程的唤醒(pthread_cond_wait)若收到唤醒通知则让队列数据出队。5.Linux多线程的基本API1.pthread_mutex_lockint pthread_mutex_lock(pthread_mutex_t *mutex);第一个传入参数pthread_mutex_t结构体指针功能这个是互斥锁加锁功能就是每次线程调用的时候都会把锁加上使其保证访问数据的原子性直到解锁为止。2. pthread_mutex_unlockint pthread_mutex_unlock(pthread_mutex_t *mutex);第一个传入参数pthread_mutex_t结构体指针功能这个是互斥锁解锁功能就是每次线程访问完资源的时候都会把锁解锁。3. pthread_cond_broadcastint pthread_cond_broadcast(pthread_cond_t *cond)传入参数pthread_cond_t的结构体指针功能唤醒所有正在pthread_cond_wait(线程等待)的线程4.pthread_cond_waitint pthread_cond_wait (pthread_cond_t *__restrict __cond , pthread_mutex_t *__restrict __mutex)第一个参数pthread_cond_t 的结构体指针第二个参数pthread_mutex_t 结构体指针功能线程等待并挂起若被唤醒了则直接跳出挂起状态。6.推流项目中视频队列的实现这张图是视频队列实现的过程VIDEO_QUEUE是一个类。这个类里面封装了添加视频队列(putVideoPacketQueue)、获取视频队列数据(getVideoPacketQueue)、获取视频队列长度(getVideoQueueSize)。1. VIDEO_QUEUE构造器这里创建一个VIDEO_QUEUE的C的构造器C构造器主要初始化了线程的量。包括线程锁的初始化(pthread_mutex_init)、线程条件变量的初始化(pthread_cond_init)。2.putVideoPacketQueue的讲解putVideoPacketQueue主要是video_data_packet_t入队的过程入队前需要加锁pthread_mutex_lock。然后进行入队操作video_packet_queue.push(video_packet)入队完成之后再通知出队线程取出队列数据pthread_cond_broadcast最后解锁pthread_mutex_unlock。3.getVideoPacketQueue的讲解getVideoPacketQueue主要是video_data_packet_t入队的过程入队前需要加锁pthread_mutex_lock。然后判断视频队列是否有数据(video_packet_queue.size()0)。若没有数据则用pthread_cond_wait去等待线程被唤醒。若队列有数据则唤醒的此线程则直接从队列取出数据。这里取出数据分两步第一步先把队列移动到最前面video_packet_queue.front()。第二步video_packet_queue.pop出队并删除数据。3.4.getVideoQueueSize的讲解getVideoQueueSize主要是获取当前队列的长度获取长度的步骤跟上面也差不多。首先pthread_mutex_lock加锁然后通过count video_packet_queue.size()获取队列的数量。然后pthread_mutex_unlock解锁。