学app软件开发多少钱网站建设一条龙全包seo

当前位置: 首页 > news >正文

学app软件开发多少钱,网站建设一条龙全包seo,wordpress query_posts 浏览量,如何制作个人网页主题是周末愉快文章目录 引言理解生产者消费者模型基于BlockingQueue的生产者消费者模型单生产#xff0c;单消费模型多生产、多消费模型 引言 生产者消费者模型一般可以在超市中听到#xff0c;例如如下是一个专门卖方便面的超市#xff0c;这个超市有自己供应商#xff0c;也有客户来买… 文章目录 引言理解生产者消费者模型基于BlockingQueue的生产者消费者模型单生产单消费模型多生产、多消费模型 引言 生产者消费者模型一般可以在超市中听到例如如下是一个专门卖方便面的超市这个超市有自己供应商也有客户来买客户称之为消费者。超市起到一个缓存作用供应商放假的时候短时间内超市依然有对应的商品消费者依然可以消费相同的如果短时间内消费者不来买东西供应商依然可以供应给超市。也就是说供应商生产产品比较慢可以先生成一批产品放在超市中供应商如果供应比较快可以等消费者消费一段时间再去供应产品协调忙线不均。现实生活中在人口密集的地方肯定会有超市生产者消费者模型效率高有了超市这个巨大的缓存可以使得消费者和生产者并发起来。
个别消费者不想买方便面不会影响到供应商个别供应商出现了问题不会影响消费者买方便面这就做到了生产者和消费者的解耦。 理解生产者消费者模型 上述例子对应到计算机中供应商和消费者就是线程超市是一段内存空间方便面是数据。生产线程将数据交到一段内存空间中消费线程从内存空间中将数据拿走。 “321原则” 一个交易场所特定数据结构的形式存在的一段内存空间两种角色生产者、消费者也就是生产线程和消费线程三种关系生产和生产互斥关系、消费和消费互斥关系、生产和消费互斥关系、同步关系 实现生产者消费者模型本质就是通过代码实现“321原则”用锁和条件变量或者其他形式来实现三种关系。 基于BlockingQueue的生产者消费者模型 在多线程编程中阻塞队列(Blocking Queue)是一种常用于实现生产者和消费者模型的数据结构。其与普通的队列区别在于当队列为空时从队列获取元素的操作将会被阻塞直到队列中被放入了元素当队列满时往队列里存放元素的操作也会被阻塞直到有元素被从队列中取出(以上的操作都是基于不同的线程来说的线程在对阻塞队列进程操作时会被阻塞)
单生产单消费模型 //BlockQueue.hpp #pragma once#includeiostream #includestring #includequeue #includepthread.hconst static int defaultcap5;templatetypename T class BlockQueue { private:bool isFull(){return _block_queue.size()_max_cap;}bool isEmpty(){return _block_queue.empty();}public:BlockQueue(int cap defaultcap):_max_cap(cap){pthread_mutex_init(_mutex,nullptr);pthread_cond_init(_P_cond,nullptr);pthread_cond_init(_C_cond,nullptr);}void Pop(T *out){pthread_mutex_lock(_mutex);while(isEmpty()){pthread_cond_wait(_C_cond,_mutex);}*out_block_queue.front();_block_queue.pop();pthread_mutex_unlock(_mutex);pthread_cond_signal(_P_cond); //唤醒生产者}void Equeue(const T in){pthread_mutex_lock(_mutex);while(isFull()) //阻塞队列满{//满了生产者不能再生产必须等待pthread_cond_wait(_P_cond,_mutex); //被调用的时候除了让自己继续排队等待还会释放自己传递的锁//函数返回时会返回在临界区必须先参与锁的竞争重新加上锁该函数才会返回依然是持有锁的状态}//阻塞队列未满或者被唤醒_block_queue.push(in); //生产数据到阻塞队列pthread_mutex_unlock(_mutex);pthread_cond_signal(_C_cond); //唤醒消费者}~BlockQueue(){pthread_mutex_destroy(_mutex);pthread_cond_destroy(_P_cond);pthread_cond_destroy(_C_cond);}private:std::queueT _block_queue; //临界资源int _max_cap;pthread_mutex_t _mutex;pthread_cond_t _P_cond; //生产者条件变量pthread_cond_t _C_cond; //消费者条件变量 };Pop 函数从队列中取出元素并将其存储在 out 指针指向的地址中。步骤如下 锁定互斥量通过 pthread_mutex_lock(_mutex) 确保对队列的操作是线程安全的。等待条件变量如果队列为空使用 pthread_cond_wait(_C_cond, _mutex) 等待消费者条件变量被信号唤醒。取出元素从队列中取出前面的元素并将其弹出。解锁互斥量通过 pthread_mutex_unlock(_mutex) 解锁。唤醒生产者使用 pthread_cond_signal(_P_cond) 唤醒可能被阻塞的生产者线程。 Equeue 函数将元素 in 插入队列。步骤如下 锁定互斥量通过 pthread_mutex_lock(_mutex) 确保对队列的操作是线程安全的。等待条件变量如果队列已满使用 pthread_cond_wait(_P_cond, _mutex) 等待生产者条件变量被信号唤醒。插入元素将新元素插入到队列中。解锁互斥量通过 pthread_mutex_unlock(_mutex) 解锁。唤醒消费者使用 pthread_cond_signal(_C_cond) 唤醒可能被阻塞的消费者线程。 为了体现阻塞队列的特点分别设计了两种测试代码 生产一个消费一个 #includeBlockQueue.hpp #includectime #includepthread.h #includeunistd.hvoid *Consumer(void *args) {BlockQueueint *bqstatic_castBlockQueueint *(args);while(true){//获取数据int data0;bq-Pop(data);//处理数据std::coutCoumer - datastd::endl;} }void *Productor(void *args) {srand(time(nullptr)^getpid());BlockQueueint *bqstatic_castBlockQueueint *(args);while(true){sleep(2);//构建数据int datarand()%101; // [1,10]//生产数据bq-Equeue(data);std::coutProductor - datastd::endl;} }int main() {BlockQueueint *bqnew BlockQueueint();pthread_t c,p;pthread_create(c,nullptr,Consumer,bq);pthread_create(p,nullptr,Productor,bq);pthread_join(c,nullptr);pthread_join(p,nullptr);return 0; }先生产一批数据直到队列开始阻塞然后消费一个生产一个 #includeBlockQueue.hpp #includectime #includepthread.h #includeunistd.hvoid *Consumer(void *args) {BlockQueueint *bqstatic_castBlockQueueint *(args);while(true){sleep(2);//获取数据int data0;bq-Pop(data);//处理数据std::coutCoumer - datastd::endl;} }void *Productor(void *args) {srand(time(nullptr)^getpid());BlockQueueint *bqstatic_castBlockQueueint *(args);while(true){//构建数据int datarand()%101; // [1,10]//生产数据bq-Equeue(data);std::coutProductor - datastd::endl;} }int main() {BlockQueueint *bqnew BlockQueueint();pthread_t c,p;pthread_create(c,nullptr,Consumer,bq);pthread_create(p,nullptr,Productor,bq);pthread_join(c,nullptr);pthread_join(p,nullptr);return 0; }上述测试代码是传递一个int类型的数据到阻塞队列中也可以传递其他类型在传递struct或者class类型时可以封装成一个个的任务传递到阻塞队列中。 传递任务 //Task.hpp #pragma once #includeiostream #includestringclass Task {public:Task(){}Task(int x,int y):_x(x),_y(y){}void Excute(){_result_x_y;}std::string debug(){std::string msgstd::to_string(_x)std::to_string(_y)?;return msg;}std::string result(){std::string msgstd::to_string(_x)std::to_string(_y)std::to_string(_result);return msg;}private:int _x;int _y;int _result; };#includeBlockQueue.hpp #includeTask.hpp #includectime #includepthread.h #includeunistd.hvoid *Consumer(void *args) {BlockQueueTask *bqstatic_castBlockQueueTask *(args);while(true){sleep(2);//获取数据Task t;bq-Pop(t);// bq-Pop(data);//处理数据t.Excute();std::coutCoumer - t.result()std::endl;} }void *Productor(void *args) {srand(time(nullptr)^getpid());BlockQueueTask *bqstatic_castBlockQueueTask *(args);while(true){//构建数据int xrand()%101;usleep(x*1000);int yrand()%101;Task t(x,y);//生产数据bq-Equeue(t);std::coutProductor - t.debug()std::endl;} }int main() {BlockQueueTask *bqnew BlockQueueTask();pthread_t c,p;pthread_create(c,nullptr,Consumer,bq);pthread_create(p,nullptr,Productor,bq);pthread_join(c,nullptr);pthread_join(p,nullptr);return 0; }传递函数任务 //Task.hpp #pragma once #includeiostream #includestring #includefunctionalusing task_tstd::functionvoid();void Download() {std::coutI am Download taskstd::endl; }//main.cc #includeBlockQueue.hpp #includeTask.hpp #includectime #includepthread.h #includeunistd.hvoid *Consumer(void *args) {BlockQueuetask_t *bqstatic_castBlockQueuetask_t *(args);while(true){sleep(2);//获取数据task_t t;bq-Pop(t);//处理数据t();} }void *Productor(void *args) {srand(time(nullptr)^getpid());BlockQueuetask_t *bqstatic_castBlockQueuetask_t *(args);while(true){bq-Equeue(Download);std::coutProductor - Download std::endl;} }int main() {BlockQueuetask_t *bqnew BlockQueuetask_t();pthread_t c,p;pthread_create(c,nullptr,Consumer,bq);pthread_create(p,nullptr,Productor,bq);pthread_join(c,nullptr);pthread_join(p,nullptr);return 0; }多生产、多消费模型 创建两个消费者线程 c1 和 c2它们会并行地从队列中取出任务并处理。创建三个生产者线程 p1、p2 和 p3它们会并行地将任务放入队列中。 //main.cc#includeBlockQueue.hpp #includeTask.hpp #includectime #includepthread.h #includeunistd.hvoid *Consumer(void *args) {BlockQueuetask_t *bqstatic_castBlockQueuetask_t *(args);while(true){//获取数据task_t t;bq-Pop(t);t();} }void *Productor(void *args) {srand(time(nullptr)^getpid());BlockQueuetask_t *bqstatic_castBlockQueuetask_t *(args);while(true){bq-Equeue(Download);std::coutProductor - Download std::endl;sleep(1);} }int main() {BlockQueuetask_t *bqnew BlockQueuetask_t();pthread_t c1,c2,p1,p2,p3;pthread_create(c1,nullptr,Consumer,bq);pthread_create(c2,nullptr,Consumer,bq);pthread_create(p1,nullptr,Productor,bq);pthread_create(p1,nullptr,Productor,bq);pthread_create(p3,nullptr,Productor,bq);pthread_join(c1,nullptr);pthread_join(c2,nullptr);pthread_join(p1,nullptr);pthread_join(p2,nullptr);pthread_join(p3,nullptr);return 0; }