提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、线程池模型
线程池模型比起多线程的优势,减少了线程创建和 线程回收的时间。
线程池的应用:
(1)程序需要设计多线程
(2)频繁的开辟线程和关闭线程
模式大概分为三个部分:
主控线程————工作线程————任务队列
模型图为:
二、使用步骤
1.线程池描述
总共设置四个线程,一个主线程用于控制子线程,三个子线程用于执行任务。
完成两者之间的沟通时需要两个技术,信号量和互斥锁。
主线程的工作:将需要的任务进行入队操作(上互斥锁),并申请一个信号量(信号量的初始值为1)。
子线程的工作:阻塞等待释放信号量,出队(上互斥锁)拿到所需的任务完成工作。
2.源码
代码如下(示例):
heah.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
#include <pthread.h>
typedef struct
{
char path[256];
FILE* fp;
}DATATYPE;
typedef struct node {
DATATYPE data;
struct node *next;
}QueueNode;
typedef struct queue {
QueueNode *head;
QueueNode *tail;
int clen;
}LinkQueue;
extern int DestroyLinkQueue(LinkQueue *queue);
extern int QuitLinkQueue(LinkQueue *queue,DATATYPE *data);
extern int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);
extern int IsFullLinkQueue(LinkQueue *queue);
extern int IsEmptyLinkQueue(LinkQueue *queue);
extern LinkQueue *CreateLinkQueue();
extern int ClearLinkQueue(LinkQueue *queue);
extern int GetHeadLinkQueue(LinkQueue *queue,DATATYPE*data);
extern int GetSizeLinkQueue(LinkQueue *queue);
#endif
fun.c
#include "head.h"
LinkQueue *CreateLinkQueue()
{
LinkQueue* temp = malloc(sizeof(LinkQueue));
if(NULL == temp)
{
perror("CreateLinkQueue malloc");
return NULL;
}
temp->head = NULL;
temp->tail =NULL;
temp->clen = 0 ;
return temp;
}
int IsEmptyLinkQueue(LinkQueue *q)
{
return 0 == q->clen ;
}
int EnterLinkQueue(LinkQueue *q, DATATYPE *data)
{
QueueNode* newnode = malloc(sizeof(QueueNode));
if(NULL == newnode)
{
perror("EnterLinkQueue malloc");
return 1;
}
memcpy(&newnode->data,data,sizeof(*data));
newnode->next= NULL;
if(IsEmptyLinkQueue(q))
{
q->head = newnode;
q->tail = newnode;
}
else
{
q->tail->next = newnode;
q->tail = newnode;
}
q->clen++;
return 0;
}
int QuitLinkQueue(LinkQueue *queue,DATATYPE *data)
{
if(IsEmptyLinkQueue(queue))
{
printf("queue is empty\n");
return 1;
}
memcpy(data,&queue->head->data,sizeof(*data));
QueueNode* temp = queue->head;
queue->head = queue->head->next;
if(NULL == queue->head)
{
queue->tail = NULL;
}
free(temp);
queue->clen--;
return 0;
}
int ClearLinkQueue(LinkQueue *queue)
{
QueueNode* temp = queue->head;
while(temp)
{
queue->head = queue->head->next;
free(temp);
temp = queue->head;
}
queue->head =NULL;
queue->tail =NULL;
queue->clen = 0;
return 0;
}
int DestroyLinkQueue(LinkQueue *queue)
{
ClearLinkQueue(queue);
free(queue);
return 0;
}
int GetHeadLinkQueue(LinkQueue *queue,DATATYPE*data)
{
if(IsEmptyLinkQueue(queue))
{
printf("queue is empty\n");
return 1;
}
memcpy(data,&queue->head->data,sizeof(*data));
return 0;
}
int GetSizeLinkQueue(LinkQueue *queue)
{
return queue->clen;
}
main.c
#include "head.h"
sem_t sem_task;
pthread_mutex_t lock;
int do_write(char* file,FILE* fp)
{
FILE* srcfp = fopen(file,"r");
if(NULL == srcfp)
{
perror("do_write, fopen");
return 1;
}
char buf[512]={0};
int num = 0;
while(1)
{
if(NULL==fgets(buf,sizeof(buf),srcfp))
{
break;
}
num++;
if(strstr(buf,"#define"))
{
fprintf(fp,"%s\t %d %s",file,num,buf);
fflush(fp);
}
}
fclose(srcfp);
return 0;
}
int do_process(char* path,LinkQueue* q ,FILE* fp,int flag) // flag 0 main, 1 subthread
{
DIR* dir = opendir(path);
DATATYPE data;
if(NULL == dir)
{
perror("opendir");
return 1;
}
struct dirent* info;
while(1)
{
info = readdir(dir);
if(NULL == info)
{
break;
}
if(DT_DIR == info->d_type)
{
if(0 == strcmp(info->d_name,".") || 0 == strcmp(info->d_name,".."))
{
continue;
}
bzero(&data,sizeof(data));
sprintf(data.path,"%s/%s",path,info->d_name);
if(0 == flag)//main
{
data.fp = fp;
pthread_mutex_lock(&lock);
EnterLinkQueue(q,&data);
pthread_mutex_unlock(&lock);
printf("main, %lu enter %s\n",pthread_self(),data.path);
sem_post(&sem_task);
}
else
{
do_process(data.path,q,fp,1);
}
}
else
{
if(strlen(info->d_name)<3)
{
continue;
}
if(0 == strcmp(&info->d_name[strlen(info->d_name)-2],".c")
||0 == strcmp(&info->d_name[strlen(info->d_name)-2],".h"))
{
sprintf(data.path,"%s/%s",path,info->d_name);
do_write(data.path,fp);
}
}
}
closedir(dir);
return 0;
}
void * th(void* arg)
{
while(1)
{
sem_wait(&sem_task);
LinkQueue* q = ( LinkQueue*)arg;
DATATYPE data;
pthread_mutex_lock(&lock);
QuitLinkQueue(q,&data);
pthread_mutex_unlock(&lock);
if(0 == strcmp(data.path,"_over_"))
{
break;
}
printf("sub, %lu quit %s\n",pthread_self(),data.path);
do_process(data.path,q,data.fp,1);
}
return NULL;
}
int main(void)
{
pthread_t tid1,tid2,tid3;
sem_init(&sem_task,0,0);
pthread_mutex_init(&lock,NULL);
LinkQueue* q = CreateLinkQueue();
pthread_create(&tid1,NULL,th,q);
pthread_create(&tid2,NULL,th,q);
pthread_create(&tid3,NULL,th,q);
FILE* fp = fopen("log.txt","w");
if(NULL == fp)
{
perror("fopen");
pthread_cancel(tid1);
pthread_cancel(tid2);
pthread_cancel(tid3);
DestroyLinkQueue(q);
exit(1);
}
do_process("/home/linux/01pute_c",q,fp,0);
printf("main thread over\n");
DATATYPE data;
int i = 0 ;
for(i = 0 ;i<3;i++)
{
strcpy(data.path,"_over_");
pthread_mutex_lock(&lock);
EnterLinkQueue(q,&data);
pthread_mutex_unlock(&lock);
sem_post(&sem_task);
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
DestroyLinkQueue(q);
sem_destroy(&sem_task);
pthread_mutex_destroy(&lock);
fclose(fp);
printf("Hello World!\n");
return 0;
}
Makefile
OBJ=all
SRC=main.o fun.o
CC=gcc
LFLAG=-g -lpthread
$(OBJ):$(SRC)
$(CC) $^ -o $@ $(LFLAG)
%.o:%.c
$(CC) -c $< -o $@
clean:
rm $(OBJ)
disclean:
rm $(OBJ) *.o