#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<queue>
using namespace std;
#define LEN 128
typedef struct task_que
{
queue<char*> string_queue;
int m_flag ; //结束标志
int m_capacity;
pthread_mutex_t m_lock;
pthread_cond_t m_pro , m_con;
}QUE , *pQUE;
void* thd_func(void* arg);
void put(pQUE pq, char* src);
void get(pQUE pq, char* dest);
int main(int argc, char *argv[])
{
QUE aque;
aque.m_flag = ;
int nthds = atoi( argv[] ); //线程的个数
aque.m_capacity = atoi( argv[] );//字符串队列的大小
pthread_mutex_init( &aque.m_lock , NULL ); //锁
pthread_cond_init( &aque.m_pro ,NULL ); //生产者条件变量
pthread_cond_init( &aque.m_con , NULL ); //消费者条件变量
//开辟线程空间
pthread_t *thd_arr = ( pthread_t*)calloc(nthds, sizeof(pthread_t));
int* ntasks = (int*)calloc(nthds, sizeof(int));//用来记录 线程工作了几次
//创建线程
int index;
for(index = ; index < nthds; index ++)
{
pthread_create( thd_arr + index, NULL, thd_func,(void*)&aque );
} //输入字符串到队列中
char buf[LEN] ;
while( memset(buf, , LEN), fgets(buf, LEN, stdin) != NULL)
{
put(&aque, buf);
} //发出结束字符串
strcpy(buf, "over");
put(&aque, buf); for(index = ; index < nthds; index ++)
{
pthread_join(thd_arr[index], (void**)(ntasks + index ));
}
for(index = ; index < nthds; index ++)
{
printf("%d ", ntasks[index]);
}
printf("\n"); pthread_mutex_destroy(&aque.m_lock);
pthread_cond_destroy(&aque.m_pro);
pthread_cond_destroy(&aque.m_con);
return ;
}
void put(pQUE pq, char* src) //把字符串写到队列中
{
pthread_mutex_lock(&pq ->m_lock); //加锁
while(pq ->string_queue.size() == pq ->m_capacity) //队列满则阻塞
{
pthread_cond_wait(&pq -> m_pro, &pq ->m_lock); }
//插入队列
char* tem = ( char*)calloc( LEN , sizeof( char ));
strcpy(tem,src);
pq->string_queue.push(tem);
pthread_mutex_unlock(&pq -> m_lock); //解锁
pthread_cond_broadcast(&pq ->m_con); //唤醒所有消费者线程 } void get(pQUE pq, char* dest)
{
pthread_mutex_lock(&pq ->m_lock); //加锁
while(pq ->m_flag == && pq ->string_queue.empty() ) //队列空 并且未结束 则阻塞
{
pthread_cond_wait(&pq ->m_con, &pq ->m_lock);
}
if(pq ->m_flag == ) //判断结束标志
{
pthread_mutex_unlock(&pq ->m_lock); //解锁
return ;
}
//出队
strcpy(dest, pq ->string_queue.front());
pq->string_queue.pop(); pthread_mutex_unlock(&pq ->m_lock);
pthread_cond_signal(&pq ->m_pro); } void* thd_func(void* arg)
{
pQUE pq = (pQUE)arg ;
char buf[LEN] ;
int ncnt = ;
while()
{
memset(buf, , LEN) ;
get(pq, buf);
if(pq ->m_flag == ) //判断结束标志
{
printf("%u exit!\n", pthread_self());
pthread_exit((void*)ncnt); //退出
}
ncnt ++ ;
printf("%u: %s\n", pthread_self(), buf); //打印字符串
if(strcmp("over", buf) == ) //判断结束字符串
{
pq ->m_flag = ; //把结束符号置为 1
pthread_cond_broadcast(&pq ->m_con); //唤醒所有线程
pthread_exit((void*)ncnt); //退出
}
if(ncnt & == ) sleep(); //简单的负载平衡
}
}

1 producer — n consumers 模型 实现的更多相关文章

  1. 6张图为你分析Kafka Producer 消息缓存模型

    摘要:发送消息的时候, 当Broker挂掉了,消息体还能写入到消息缓存中吗? 本文分享自华为云社区<图解Kafka Producer 消息缓存模型>,作者:石臻臻的杂货铺. 在阅读本文之前 ...

  2. kafka consumer重复消费问题

    在做分布式编译的时候,每一个worker都有一个consumer,适用的kafka+zookeep的配置都是默认的配置,在消息比较少的情况下,每一个consumer都能均匀得到互不相同的消息,但是当消 ...

  3. python--线程知识详解

    Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1.1.threading模块 threading模块建立在_thread模块之上.thread模块以低级=原始的方式来处理 ...

  4. java 中多线程之间的通讯之等待唤醒机制

    wait notify () nitifyAll () 都使用在同步中,因为要对持有监视器(锁)的线程操作 所以要使用在同步中,因为只有同步才具有锁 为什么这些操作线程的方法要定义object类中呢 ...

  5. 关于LockSupport

    concurrent包的基础 Doug Lea 的神作concurrent包是基于AQS (AbstractQueuedSynchronizer)框架,AQS框架借助于两个类:Unsafe(提供CAS ...

  6. 二十二、Hadoop学记笔记————Kafka 基础实战 :消费者和生产者实例

    kafka的客户端也支持其他语言,这里主要介绍python和java的实现,这两门语言比较主流和热门 图中有四个分区,每个图形对应一个consumer,任意一对一即可 获取topic的分区数,每个分区 ...

  7. IBM developer:Kafka ACLs

    Overview In Apache Kafka, the security feature is supported from version 0.9. When Kerberos is enabl ...

  8. Kafka Frequently Asked Questions

    This is intended to be an easy to understand FAQ on the topic of Kafka. One part is for beginners, o ...

  9. Benchmarking Apache Kafka: 2 Million Writes Per Second (On Three Cheap Machines)

    I wrote a blog post about how LinkedIn uses Apache Kafka as a central publish-subscribe log for inte ...

随机推荐

  1. 洛谷 P1031 均分纸牌

    P1031 均分纸牌 这道题告诉我们,对于实在想不出算法的题,可以大胆按照直觉用贪心,而且在考试中永远不要试着去证明贪心算法,因为非常难证,会浪费大量时间. (这就是你们都不去证的理由??) 这道题贪 ...

  2. Windows忘记mysql的密码

    1.查看mysql的安装路径 show variables like "%char%"; 路径:C:\Program Files\MySQL\MySQL Server 5.7\ 2 ...

  3. WPF 控件树

    WPF控件树按照基类进行分类,记录下来便于编写自定义控件时查阅 RangeBase范围控件 Thumb拖到控件 TextBoxBase文本控件 ItemControl组控件 ContrentContr ...

  4. aspx页面调用webapi接口报错:远程服务器返回错误:(500)内部服务器错误

    代码在运行到response = (HttpWebResponse)request.GetResponse();就开始报错 原因:可能因为所调用的接口不存在或者接口中存在错误,可用postman测试接 ...

  5. 用redis实现简单的队列

    在工作中,时常会有用到队列的场景,比较常见的用rabbitMQ这些专业的组件,官网地址是:http://www.rabbitmq.com,重要的是官方有.net的客户端,但是如果对rabbitMQ不熟 ...

  6. 理解C#系列 / 前言

    前言 索引 写什么? 为什么写? 怎么写? 写什么? 写和C#编程相关的知识. 写知识的定义,附加对知识的理解. 写知识的作用,使用的场景,使用的条件. 写知识的本质,技术的结构,工作的原理. 写知识 ...

  7. PLSQL连接Oracle64监听和服务的配置!

    前言: 这里不会涉及到太多关于版本问题的解决,只是简单提一下基本的监听和服务配置问题的解决,让你可以快速的用PLSQL连接上你自己创建的Oracle数据库(这里示例数据库名为ORCL); 版本问题: ...

  8. uvm_reg_defines——寄存器模型(四)

    文件: src/marcos/uvm_reg_defines 类: 无 该文件是寄存器模型src/reg/* 文件对于的宏文件,主要定义了寄存器地址位宽,寄存器数据位宽,字节的大小.计算机从最初的8, ...

  9. run_test() 验证平台的入口

    Run,just run!    ——阿甘正传   一个简单的例子: module tb_top; dut u_dut (); initial begin run_test(); end config ...

  10. IDEA 启用/禁用 Run Dashboard

    一.启用 方式一: 创建/打开一个SpringBoot项目[或者点击Run --> Edit Configurations 添加 Spring Boot 类型的项目配置:或者如图在红框处添加配置 ...