1 producer — n consumers 模型 实现
#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 模型 实现的更多相关文章
- 6张图为你分析Kafka Producer 消息缓存模型
摘要:发送消息的时候, 当Broker挂掉了,消息体还能写入到消息缓存中吗? 本文分享自华为云社区<图解Kafka Producer 消息缓存模型>,作者:石臻臻的杂货铺. 在阅读本文之前 ...
- kafka consumer重复消费问题
在做分布式编译的时候,每一个worker都有一个consumer,适用的kafka+zookeep的配置都是默认的配置,在消息比较少的情况下,每一个consumer都能均匀得到互不相同的消息,但是当消 ...
- python--线程知识详解
Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1.1.threading模块 threading模块建立在_thread模块之上.thread模块以低级=原始的方式来处理 ...
- java 中多线程之间的通讯之等待唤醒机制
wait notify () nitifyAll () 都使用在同步中,因为要对持有监视器(锁)的线程操作 所以要使用在同步中,因为只有同步才具有锁 为什么这些操作线程的方法要定义object类中呢 ...
- 关于LockSupport
concurrent包的基础 Doug Lea 的神作concurrent包是基于AQS (AbstractQueuedSynchronizer)框架,AQS框架借助于两个类:Unsafe(提供CAS ...
- 二十二、Hadoop学记笔记————Kafka 基础实战 :消费者和生产者实例
kafka的客户端也支持其他语言,这里主要介绍python和java的实现,这两门语言比较主流和热门 图中有四个分区,每个图形对应一个consumer,任意一对一即可 获取topic的分区数,每个分区 ...
- IBM developer:Kafka ACLs
Overview In Apache Kafka, the security feature is supported from version 0.9. When Kerberos is enabl ...
- 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 ...
- 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 ...
随机推荐
- Jasper_crosstab_headerPosition_columngroup header position config - (headerPosition="Stretch")
i.e <columnGroup name="column11" height="20" totalPosition="Start" ...
- HTML图像标记
1.使用方法 <img src="路径/文件名.图片格式" width="属性值" height="属性值" border=" ...
- link标签的media属性的用法
<link rel=stylesheet" type="text/css" href="print.css" media="scree ...
- 海康威视采集卡结合opencv使用(两种方法)-转
(注:第一种方法是我的原创 ^_^. 第二种方法是从网上学习的.) 第一种方法:利用 板卡的API: GetJpegImage 得到 Jpeg 格式的图像数据,然后用opencv里的一个函数进行解码 ...
- cacti添加被监控机全过程
在被监控端上的操作: 1.在被监控机器上root目录下建立文件 test.sh chmod 777 test.sh cat test #!/bin/bash echo $RANDOM 2.在snmpd ...
- 这么大一座Azure“图书馆”,你竟没有发现…
为避免被叫做「伸手党」,很多技术人员早已养成遇到问题上网搜的好习惯. 然而…… 同一个概念,搜到两个相互矛盾的解释,以谁的为准? 想查找某个 API 的用法,搜索结果数十万条,怎样筛选出最有价值的? ...
- Android学习总结(十六) ———— MediaPlayer播放音频与视频
一.基本概念 本文主要介绍的是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的架构.Android的MediaPlayer包含了Audio和video的播放功能,在Andr ...
- CodeForces 219D Choosing Capital for Treeland (树形DP)
题意:给一个树形图,n个节点,n-1条有向边,要求选一个节点作为根,使需要改变方向的边的数目最少.并输出所有可能作为根的点. 思路: 先随便一个点进行DFS,计算将每棵子树的边全部往下时,所需要的费用 ...
- COGS 264. 数列操作
时间限制:1 s 内存限制:160 MB [问题描述] 假设有一列数 {Ai }(1 ≤ i ≤ n) ,支持如下两种操作: (1)将 A k 的值加 D .( k, D 是输入的数) (2) 输 ...
- 联想e431笔记本更改硬盘模式bios设置的详细教程
用硬盘安装系统,就要进入bios,将硬盘改为第一启动项即可重装系统.不同品牌的电脑,它的bios设置方法也就不同.那么,联想e431笔记本要如何更改硬盘模式呢?今天U大侠小编就和大家分享联想e431笔 ...