wordpress无法用ftp,网站优化课程培训,网站缩略图存哪里好,ipv6域名解析 做网站### 循环队列和阻塞队列
#### 循环队列 - **定义**: 一个固定大小的数组#xff0c;通过两个指针#xff08;front 和 back#xff09;管理队列的头部和尾部元素。 - **特点**: - **循环性**: 当指针到达数组的末尾时#xff0c;可以回绕到数组的开头#xff0c;从而利…### 循环队列和阻塞队列
#### 循环队列 - **定义**: 一个固定大小的数组通过两个指针front 和 back管理队列的头部和尾部元素。 - **特点**: - **循环性**: 当指针到达数组的末尾时可以回绕到数组的开头从而利用数组的全部空间。 - **空间效率**: 使用固定大小的数组避免了动态内存分配和释放带来的开销。
#### 阻塞队列 - **定义**: 一种线程安全的队列在队列为空时尝试出队的线程会被阻塞在队列已满时尝试入队的线程也会被阻塞。 - **特点**: - **线程安全**: 使用互斥锁和条件变量来保证多线程环境下的安全访问。 - **阻塞机制**: 当队列为空或已满时通过条件变量阻塞相应的线程直到队列状态发生改变。
### 阻塞队列与生产者-消费者模型
#### 生产者-消费者模型 - **定义**: 一种经典的多线程同步模型通常涉及两个角色生产者和消费者。 - **生产者**: 负责生产数据并将其放入队列。 - **消费者**: 负责从队列中取出数据进行处理。 - **特点**: - **解耦**: 生产者和消费者通过共享队列进行数据交换彼此之间解耦。 - **同步**: 使用阻塞队列来实现生产者和消费者之间的同步。
### 阻塞队列与异步日志系统
#### 异步日志系统 - **定义**: 一种日志记录系统其中日志记录操作与业务逻辑操作分离通过异步机制提高性能。 - **特点**: - **非阻塞**: 业务逻辑线程将日志消息放入队列后立即返回而不是等待日志写入完成。 - **后台处理**: 专门的日志线程从队列中取出日志消息并写入日志文件。
#### 阻塞队列在异步日志系统中的应用 - **队列**: 用于存放日志消息。 - **生产者**: 业务逻辑线程将日志消息放入队列。 - **消费者**: 日志处理线程从队列中取出日志消息并写入日志文件。 - **同步**: 通过阻塞队列实现生产者和消费者的同步确保日志消息不会丢失且处理有序。
### 代码分析
- **构造函数**: 初始化队列的最大大小和内部数组。 - **析构函数**: 销毁队列释放内存。 - **清空队列**: 清空队列内容并重置指针。 - **检查队列状态**: 判断队列是否为空或已满。 - **获取队首和队尾元素**: 安全地获取队列的首尾元素。 - **入队和出队操作**: 提供线程安全的入队和出队操作使用条件变量实现阻塞机制。
总的来说这个阻塞队列通过互斥锁和条件变量实现了多线程环境下的安全访问和同步机制可以用于生产者-消费者模型中实现高效的异步日志系统。 #ifndef BLOCK_QUEUE_H #define BLOCK_QUEUE_H #includeiostream #includestdio.h #includepthread.h #includesys/time.h #include../lock/locker.h using namespace std; templateclass T class block_queue{ public: /*初始化阻塞队列*/ block_queue(int max_size) { if (max_size 0) { exit(-1); } m_max_size max_size; T* m_array new T[max_size]; m_size 0; m_front -1; m_back -1; } /*删除new出的T数组*/ ~block_queue() { m_mutex.lock(); if (m_array ! NULL) { delete []m_array; } m_mutex.unlock(); } /*清空队列*/ void clear() { m_mutex.lock(); m_size 0; m_front -1; m_back -1; m_mutex.unlock(); } /*判断队列是否已满*/ bool full() { m_mutex.lock(); if (m_size m_max_size) { m_mutex.unlock(); return true; } m_mutex.unlock(); return false; } /*判断队列是否为空*/ bool empty() { m_mutex.lock(); if (m_size 0) { m_mutex.unlock(); return true; } m_mutex.unlock(); return false; } /*获得队首元素*/ bool front(T value) { m_mutex.lock(); /*注意下面的if判断不能用empty因为empty函数也有加锁操作加两次锁会导致死锁*/ if (size 0) { m_mutex.unlock(); return false; } //TODO:个人感觉这行逻辑出错后面部分是原代码 value m_array[m_front]; value m_array[(m_front 1) % m_max_size]; m_mutex.unlock(); return true; } /*获得队尾元素*/ bool back(T value) { m_mutex.lock(); if (size 0) { m_mutex.unlock(); return false; } value m_array[m_back]; m_mutex.unlock(); return true; } int size() { int tmp 0; m_mutex.lock(); tmp m_size; m_mutex.unlock(); return tmp; } int max_size() { int tmp 0; m_mutex.lock(); tmp m_max_size; m_mutex.unlock(); return tmp; } /*往队列中添加元素前需要先将所有使用队列的线程先唤醒*/ /*阻塞队列封装了生产者消费者模型调用push的是生产者也就是工作线程*/ bool push(T item) { m_mutex.lock(); if (m_size m_max_size) { cond.broadcast(); m_mutex.unlock(); return false; } m_back (m_back 1) % m_max_size; m_array[m_back] item; m_size; cond.broadcast(); m_mutex.unlock(); return true; } /*调用pop的是消费者负责把生产者的内容写入文件*/ bool pop(T item) { m_mutex.lock(); while (m_size 0) { if (!cond.wait(m_mutex.get())) { m_mutex.unlock(); return false; } } m_front (m_front 1) % m_max_size; item m_array[m_front]; m_size--; m_mutex.unlock(); return true; } bool pop(T item,int ms_timeout) { struct timespec t {0,0};//tv_sec 从1970年1月1日 0点到现在的秒数 tv_nsec:tv_sec后面的纳秒数 struct timeval now {0,0};//tv_sec: 从1970年1月1日 0点到现在的秒数 tu_usec:tv_sec后面的微妙数 gettimeofday(now,nullptr); m_mutex.lock(); if (m_size 0) { t.tv_sec now.tv_sec ms_timeout/1000; t.tv_nsec (ms_timeout % 1000) * 1000; if (!m_cond.timewait(m_mutex.get(), t)) { m_mutex.unlock(); return false; } } //TODO:这一块代码的意义不知道在哪里留着DEBUG if (m_size 0) { m_mutex.unlock(); return false; } m_front (m_front 1) % m_max_size; item m_array[m_front]; m_size--; m_mutex.unlock(); return true; } private: locker m_mutex; cond m_cond; T* m_array; int m_max_size; int m_size; int m_front; int m_back; }; #endif