您的位置:首页 > 其它

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

2017-09-01 00:11 423 查看
队列遵循先进先出,那么其实跟链表的尾插就类似的,正好,利用这个特性,可以实现一个简单的等待队列程序软件框架,设计这条队列时,我们依然还是会使用头节点这个东西,但是它在队列中只是存储关键数据,并不是真正意义上的节点,可以将它忽略。
这个等待队列可以设计为以下数据结构:工作者结构+基本队列链式结构
所以可以设计出以下结构体:
//工作者结构
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 ;
}
运行结果:


程序仍需优化,预知详情,请看下回分解。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: