2024年简 易 版 线 程 池 模 型 学 习_que_get,2024年最新阿里P7大牛亲自教你

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

队列数据结构
typedef struct tag_node{
int newfd;
struct tag_node *pnext;
}node_t,*pnode_t;

typedef struct {
pnode_t phead,ptail; //定义头尾指针
int capability; //可以承载最多业务的最大能力
int size; //当前队列中的任务业务数
pthread_mutex_t mutex; //定义队列锁
}que_t,*pque_t;

线程池数据结构及网络发送数据的数据结构–小火车模型
typedef struct{ //所有的数据结构
que_t que; //队列
pthread_cond_t cond; //定义线程条件变量
pfunc downfile; //定义子线程入口地址函数
pthread_t *pth; //线程ID的数组名,即首地址
int pth_num; //创建的线程数
short startflag; //线程池启动标志
}factory,*pfac;

typedef struct{
int len;
char buf[1000];
}train,*ptrain;


**3、需要完成的部分功能函数**



队列的部分功能函数:
void que_init(pque_t);
void que_insert(pque_t ,pnode_t);
void que_get(pque_t ,pnode_t *);

线程功能函数的:

void factory_init(pfac p,int pth_num,pfunc pth_handle);
void factory_start(pfac p);

void send_data(int);
int send_n(int ,char *,int);


**4、头文件**



//head.h

#ifndef __HEAD_H__
#define __HEAD_H__
#include<sys/stat.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include<sys/wait.h>
#include<pthread.h>

#endif

//work_que.h
#ifndef __WORK_QUE_H__
#define __WORK_QUE_H__
#include"head.h"

#define CAP 1000

typedef struct tag_node{
int newfd;
struct tag_node *pnext;
}node_t,*pnode_t;

typedef struct {
pnode_t phead,ptail; //定义头尾指针
int capability; //可以承载最多业务的最大能力
int size; //当前队列中的任务业务数
pthread_mutex_t mutex; //定义队列锁
}que_t,*pque_t;

void que_init(pque_t);
void que_insert(pque_t ,pnode_t);
void que_get(pque_t ,pnode_t *);
#endif

//factory.h
#ifndef __FACTORY_H__
#define __FACTORY_H__
#include"head.h"
#include"work_que.h"

typedef void *(*pfunc)(void *);
#define FILENAME “file”

typedef struct{ //所有的数据结构
que_t que; //队列
pthread_cond_t cond; //定义线程条件变量
pfunc downfile; //定义子线程入口地址函数
pthread_t *pth; //线程ID的数组名,即首地址
int pth_num; //创建的线程数
short startflag; //线程池启动标志
}factory,*pfac;

typedef struct{
int len;
char buf[1000];
}train,*ptrain;

void factory_init(pfac p,int pth_num,pfunc pth_handle);
void factory_start(pfac p);

void send_data(int);
int send_n(int ,char *,int);
#endif


**5、主函数代码**



#include"factory.h"

void *pth_handle(void *p)
{
pfac pf=(pfac)p;
pque_t pq=&pf->que;
pnode_t pcur; //要拿的节点,因为一会儿要free掉
while(1)
{
pthread_mutex_lock(&pq->mutex); //拿节点之前,加锁
//且首先判断队列为不为空
if(NULL==pq->phead)
{
//为空子线程就等待
pthread_cond_wait(&pf->cond,&pq->mutex);
}
//否则,先拿到节点,解锁后,进行服务,传文件
que_get(pq,&pcur); //拿节点
pthread_mutex_unlock(&pq->mutex); //解锁
send_data(pcur->newfd); //发送文件
free(pcur); //释放掉节点
}
}

int main(int argc,char **argv)
{
if(4!=argc)
{
printf(“please input IP PORT PTHREAD_NUM\n”);
return -1;
}
factory p;
bzero(&p,sizeof§);
int pth_num=atoi(argv[3]);
factory_init(&p,pth_num,pth_handle);
factory_start(&p);
int sfd;
sfd=socket(AF_INET,SOCK_STREAM,0);
if(-1sfd)
{
perror(“socket”);
return -1;
}
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2])); //需要把它置为网络字节序
ser.sin_addr.s_addr=inet_addr(argv[1]);
int ret;
ret=bind(sfd,(struct sockaddr *)&ser,sizeof(ser));
if(-1
ret)
{
perror(“bind”);
return -1;
}
listen(sfd,pth_num);
int newfd;
pnode_t pnew; //拿节点
pque_t pq=&p.que; //为了后面的书写方便

//主线程接受请求,插入队列,子线程服务请求,拿走队列节点
while(1)
{
    newfd=accept(sfd,NULL,NULL);//这里是第二个是客户端的信息
    pnew=(pnode_t)calloc(1,sizeof(node_t));    //这是节点呀
    pnew->newfd=newfd;          //将连接的描述符给申请空间的新节点
    pthread_mutex_lock(&pq->mutex);    //插入节点前先加锁
    que_insert(pq,pnew);                 //第二个参数已经是指针了
    pthread_mutex_unlock(&pq->mutex);    //插入后在解锁
    //由于插入新节点后,就应该通知子线程有任务到达
    pthread_cond_signal(&p.cond);       //不要混淆呀

}

}


**6、队列部分函数实现work\_que.c**



#include"work_que.h"

void que_init(pque_t que)
{
que->capability=CAP;
pthread_mutex_init(&que->mutex,NULL);
}

void que_insert(pque_t pq,pnode_t pnew)
{
if(NULL==pq->ptail) //若队列为空
{
pq->phead=pnew;
pq->ptail=pnew; //头尾指针都指向pnew
}else{ //否则,进行尾插法
pq->ptail->pnext=pnew;
pq->ptail=pnew;
}
pq->size++; //操作完后,大小自动加一,表示有新请求
}

void que_get(pque_t pq,pnode_t *pcur) //拿是拿指向该节点的指针
{
*pcur=pq->phead; //头删–即从头部取节点
pq->phead=pq->phead->pnext;
//拿完之后需要在判断是否为空
if(NULL==pq->phead)
{
pq->ptail=NULL; //若为空将尾指针也置为NULL
}
pq->size–;
}


**7、线程池工厂功能函数**



#include"factory.h"

void factory_init(pfac p,int pth_num,pfunc pth_handle) //不要混淆呀
{
que_init(&p->que);
pthread_mutex_init(&p->que.mutex,NULL);
pthread_cond_init(&p->cond,NULL);
p->downfile=pth_handle;
p->pth=(pthread_t *)calloc(pth_num,sizeof(pthread_t));
p->pth_num=pth_num;
p->startflag=0;
}

void factory_start(pfac p)
{
int i;
if(0==p->startflag)
{
for(i=0;ipth_num;i++)
{
pthread_create(p->pth+i,NULL,p->downfile,p);
}
p->startflag=1; //将线程启动标志位置为1(即启动)
}
}


**8、发送文件及循环发送功能函数**



#include"factory.h"

void send_data(int newfd)
{
train t;
memset(&t,0,sizeof(t));
strcpy(t.buf,FILENAME);
t.len=strlen(FILENAME);
printf(“the strcpy t.buf is %s, len =%d\n”,t.buf,t.len);
//先发文件名
int ret;
ret=send_n(newfd,(char )&t,t.len+4);
if(ret==-1)
{
perror(“send”);
return;
}
int fd=open(FILENAME,O_RDONLY);
if(-1==fd)
{
perror(“open”);
return;
}
struct stat filestat;
fstat(fd,&filestat);
t.len=sizeof(long);
memcpy(t.buf,&filestat.st_size,sizeof(filestat.st_size));
send_n(newfd,(char
)&t,4+t.len);
while(memset(t.buf,0,sizeof(t.buf)),(t.len=read(fd,t.buf,sizeof(t.buf)))>0)
{
send_n(newfd,(char *)&t,t.len+4);

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

*)&t,t.len+4);

[外链图片转存中…(img-DMaxdEmn-1715794716130)]
[外链图片转存中…(img-5v2eeqVo-1715794716131)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值