设计一条简单的等待工作队列之软件模型设计与实现(一)-阿里云开发者社区

开发者社区> 云计算> 正文

设计一条简单的等待工作队列之软件模型设计与实现(一)

简介: 队列遵循先进先出,那么其实跟链表的尾插就类似的,正好,利用这个特性,可以实现一个简单的等待队列程序软件框架,设计这条队列时,我们依然还是会使用头节点这个东西,但是它在队列中只是存储关键数据,并不是真正意义上的节点,可以将它忽略。

队列遵循先进先出,那么其实跟链表的尾插就类似的,正好,利用这个特性,可以实现一个简单的等待队列程序软件框架,设计这条队列时,我们依然还是会使用头节点这个东西,但是它在队列中只是存储关键数据,并不是真正意义上的节点,可以将它忽略。

这个等待队列可以设计为以下数据结构:工作者结构+基本队列链式结构

所以可以设计出以下结构体:

//工作者结构
typedef struct __work_st
{
	//工作者编号 
	int work_serial_num;
	//工作者执行操作 
	void (*queue_st)(); 
}work_st ; 

//队列结构体实现 
typedef struct queue_st
{
	work_st work_queue ;
	//队列的最大长度
	int queue_max_length ; 
	//队列的实际长度
	int queue_length ; 
	//队列是否为空的标志
	int Null_flag ;
	//队列是否为满的标志
	int Full_flag ; 
	//指向下一个队列节点 
	struct queue_st *next ;
}queue_list;

设计这个数据结构的解析如下:

(1)工作者结构中:

work_serial_num用来记录当前工作者的标号,主要用来记录工作者的顺序。

void (*queue_st)();是一个函数指针,这个指针就是所谓的工作,每一个队列节点就是一条工作队列,具体实现什么样的工作可以自己去实现它。

(2)队列结构体:

work_queue就是对应工作者结构,将来核心的执行区域就是它。

queue_max_length是记录队列的最大长度,这个可以在初始化队列头节点的时候给定。

queue_length是记录当前队列的长度,也有引用计数的作用,如果有工作者入队,计数加一,出队,计数减一。

Null_flag是记录当前队列是否为空的标志位。

Full_flag是记录当前队列是否为满的标志位

struct queue_st *next是队列指针域

画一幅图来描述下这个设计的实现:


下面可以来实现这个软件框架模型:

我们需要定义队列的实现函数:

//初始化队列头---->虚设,没有意义,只是为了方便操作 
void Init_queue_header(queue_list *header , int queue_length) ; 
//检查当前队列是否已经满了 ,通过队列满标志和队列最大长度这两个条件同时成立来判断 
int Check_queue_full(queue_list *header , int queue_length);
//入队--->将要执行的编号和功能函数注册到队列中去 
int En_queue(queue_list *header , work_st *workArray) ;
//出队--->每个编号对应的功能函数会对应创建一条线程,等待第一条工作队列结束后,才会执行接下来的
//工作。 
queue_list *De_queue(queue_list *header) ;
//检查当前的队列是否为空,检查的标准是不包括队列头,通过引用计数来计算队列的长度 
int Check_queue_null(queue_list *header) ;
//获取当前队列的长度,不包括队列头 
int Get_queue_Length(queue_list *header) ;
下面来实现一下这个程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<pthread.h>
#include <Windows.h>
#define QUEUE_LEN  10 


//工作者结构
typedef struct __work_st
{
	//工作者编号 
	int work_serial_num;
	//工作者执行操作 
	void (*queue_st)(); 
}work_st ; 

//队列结构体实现 
typedef struct queue_st
{
	work_st work_queue ;
	//队列的最大长度
	int queue_max_length ; 
	//队列的实际长度
	int queue_length ; 
	//队列是否为空的标志
	int Null_flag ;
	//队列是否为满的标志
	int Full_flag ; 
	//指向下一个队列节点 
	struct queue_st *next ;
}queue_list;

//初始化队列头---->虚设,没有意义,只是为了方便操作 
void Init_queue_header(queue_list *header , int queue_length) ; 
//检查当前队列是否已经满了 ,通过队列满标志和队列最大长度这两个条件同时成立来判断 
int Check_queue_full(queue_list *header , int queue_length);
//入队--->将要执行的编号和功能函数注册到队列中去 
int En_queue(queue_list *header , work_st *workArray) ;
//出队--->每个编号对应的功能函数会对应创建一条线程,等待第一条工作队列结束后,才会执行接下来的
//工作。 
queue_list *De_queue(queue_list *header) ;
//检查当前的队列是否为空,检查的标准是不包括队列头,通过引用计数来计算队列的长度 
int Check_queue_null(queue_list *header) ;
//获取当前队列的长度,不包括队列头 
int Get_queue_Length(queue_list *header) ;

void print(queue_list *header)
{
	sleep(1);
	printf("work_serial_num: %d   hello kitty.....!\n",header->work_queue.work_serial_num);
}

void print1(queue_list *header)
{
	sleep(1);
	printf("work_serial_num: %d   hello world.....!\n",header->work_queue.work_serial_num);
}


//执行工作队列里的任务,每个任务都是一条线程 
work_st work_array[] = 
{
	{1,print},
	{2,print1},
	{3,print1},
};

int main(void)
{
	int ret = 0 ; 
	queue_list *queue_node = NULL ;
	queue_node =  malloc(sizeof(queue_list));
	//检查队列是否为空队列
	if(queue_node == NULL)
	{
		printf("队列申请内存为失败!\n");
		return -1 ;
	}
	printf("queue_node mem:0x%p\n",queue_node);
	//初始化工作队列头 
	Init_queue_header(queue_node,3);//QUEUE_LEN
	//入队
	printf("入队:\n");
	En_queue(queue_node , &work_array[0]);
    En_queue(queue_node , &work_array[1]);
    En_queue(queue_node , &work_array[2]);
    //获取当前队列的长度
    printf("入队后:\n");
	ret = Get_queue_Length(queue_node); 
	printf("当前队列的长度:%d\n",ret);
	printf("----------------------------------------------------------------\n");
	queue_node = De_queue(queue_node);
	printf("出队后:\n");
	if(queue_node != NULL)
		printf("队列不是空的!\n");
	return 0 ;	
} 


//初始化队列头节点 
void Init_queue_header(queue_list *header , int queue_max_length)
{
	queue_list *p = header ;	
	p->work_queue.work_serial_num = 0 ; 
	p->work_queue.queue_st = NULL ;
	p->queue_length = 0 ;
	p->queue_max_length = queue_max_length ;
	//默认初始化队列的时候,保存的NULL_flag是生效的 
	p->Null_flag = 1 ; 
	//默认是不生效的 
	p->Full_flag = 0 ;
	p->next = NULL ;
}

//检查队列是否为空 
//return 1 为空
//return !1  不为空 
int Check_queue_null(queue_list *header)
{
	queue_list *p = header ;
	if(NULL == p)
		return 1 ;
	if(p->Null_flag) 
	{
		p->Null_flag = 1;
		return p->Null_flag ;
	}
	p->Null_flag = 0 ;
	return p->Full_flag ;
}

//检查队列是否已经满了 
//       : 1  为满 
int Check_queue_full(queue_list *header , int queue_length)
{
	queue_list *p = header ;
	if(queue_length == p->Full_flag && queue_length == p->queue_max_length)
		return 1 ;
}

//获取当前队列的长度 
int Get_queue_Length(queue_list *header)
{
	queue_list *p = header ;
	if(NULL == p)
		return -1 ;
	return p->queue_length ;
}

//入队 
int En_queue(queue_list *header , work_st *workArray)
{
	queue_list *p = header ;
	queue_list *New = NULL ; 
	New = malloc(sizeof(queue_list));
	if(NULL == New){
		fprintf(stderr , "分配失败!\n");
		return ;
	}
	memset(New,0,sizeof(queue_list));
	p->queue_length++ ;
	if(p->queue_length > p->queue_max_length){
		printf("队列已满!不能再插入数据\n");
		p->Full_flag = 1 ;
		p->queue_length-- ;
		return -1;
	}
	New->work_queue.work_serial_num = workArray->work_serial_num ;
	New->work_queue.queue_st = workArray->queue_st ;
	p->Full_flag = 0 ;
	p->Null_flag = 0 ;
	while(NULL != p->next)  
		p = p->next ;
	New->next = p->next ; 
	p->next = New ; 
}

//出队 
queue_list *De_queue(queue_list *header)
{
	queue_list *temp = header;
	queue_list *p = header ;
	queue_list *prev ;
	int count = 0;
	int queue_num_count = 0 ;
	int ret ;
	pthread_t tid ;
	while(NULL != p->next)
	{
		prev = p ;
		//指向下一个工作 
		p = p->next ;
		//每插入一个节点,就相当于创建一条线程来执行对应的工作 
		ret = pthread_create(&tid , NULL , (void *)p->work_queue.queue_st, p);
		if(ret < 0){
			printf("create work_thread fair!ssssssssssssssssssssssssss\n");
			return ;
		}
		//等待对应的工作结束 
		pthread_join(tid,NULL);
		printf("queue_p mem:0x%p\n",p);
		//保存当前队列的前一个指针的地址 
		if(NULL != p->next)
		{
			prev->next = p->next ;
			//出队引用计数减一 
			header->queue_length-- ;
			free(p);
		}
		else
		{
			p->next = NULL ; 
			//出队引用计数减一 
			header->queue_length-- ;
			free(p);
		}
		printf("queue_len:%d\n",header->queue_length);
	}
	//将头节点也删除 
	free(temp);
	temp = NULL ;
	return temp ;
}
运行结果:


程序仍需优化,预知详情,请看下回分解。。。。



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
云计算
使用钉钉扫一扫加入圈子
+ 订阅

时时分享云计算技术内容,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

其他文章