线程池

前言

	最初一开始的时候,我们是采用一种一个任务一个线程(进程,其实在内核看来进程和线程都是一个东西)运行。
	任务一做完,进程(线程)就要销毁,所有的空间都要收回。
	但是很多时候,时间花在了销毁和创建进程。
	我们仔细想想我们人在工作的时候,工作做完了,任务完成了,但是人没有消亡。
	映射在这里是不是可以让进程(线程)不要关闭,等待任务的到来。

想法

既然我们想让进程不要消亡,那么就要解决掉如下问题:
	1.接收、管理任务。
	2.管理忙碌的线程,空闲的进程。
	3.帮助相应的进程(线程)找到没有处理的任务。
	4.监控线程,查看是不是出现了问题。(非必要)

解决方案

问题一:
	首先我们需要在接收到任务的时候:
		不是立即开始创建一个进程,而是将一个线程分配出去工作。
		那么就会出现线程不够的问题,导致这个任务第一时间无法解决。
	所以我们需要一种数据结构,保存一下任务请求。
	
	我们需要选择一个比较好的数据结构,符合这个任务池需求和性质
		1.遵循先来先服务原则,优先考虑队列
		2.任务是大小不确定的、分高峰期和低谷期,优先考虑是链式结构。
		3.任务一来通知其他的线程开始工作。(特殊性)
	
	所以我们选择双向链式队列进行保存任务请求。

问题二:
	首先我们需要多个线程,这些线程是永久性存在的。
		同样我们需要选一种数据结构,保存下来这些线程
	我们首先先分休闲线程池和忙碌线程池两种:
		休闲线程池:
			1.管理所有空闲线程
			2.可以在任意的地方取出线程,放入忙碌线程
		忙碌线程池:
			1.管理所有的忙碌线程
			2.每一个线程都有可能最先完成,需要频繁中间删除
	忙碌线程池优先考虑双向链式顺序表,为了避免在写很多的代码,也可以考虑将休闲线程池做成和忙碌线程池一样的

问题三:
	关于任务组装的问题:
	我们可以考虑使用函数指针方法进行组装。		
#include "pool.h"
PTHREAD_QUEUE * pthread_leisure_queue;
PTHREAD_QUEUE * pthread_busy_queue;
TASK_QUEUE * task_NeedWork_queue;
void sys_clean(void)
{
    perror("system error");
    exit(EXIT_FAILURE);
}
void * Pthread_Work(void * ptr)
{
    PTHREAD_NODE * self = (PTHREAD_NODE *) ptr;
    pthread_mutex_lock (&self->mutex);
    //self->tid = gettid();
    self->tid = syscall (SYS_gettid);
    pthread_mutex_unlock (&self->mutex);
    while (1)
    {
        pthread_mutex_lock (&self->mutex);
        if(self->work==NULL)
            pthread_cond_wait(&self->cond,&self->mutex);
        pthread_mutex_lock (&self->work->mutex);
        self->work->fun(self->work->arg);
        self->work->fun = NULL;
        free(self->work->arg);
        self->work->flag = 0;
        self->next = NULL;
        self->tid = 0;
        self->work->arg=NULL;
        pthread_mutex_unlock (&self->work->mutex);
        free (self->work);
        self->work = NULL;

        pthread_mutex_lock(&pthread_busy_queue->mutex);
        if(pthread_busy_queue->size==1)
        {
            pthread_busy_queue->rear = NULL;
            pthread_busy_queue->head = NULL;
        }
        else if(pthread_busy_queue->rear==self&&pthread_busy_queue->head!=self)
        {
            pthread_busy_queue->rear = self->prev;
            pthread_busy_queue->rear->next = NULL;
        }
        else if(pthread_busy_queue->head == self && pthread_busy_queue->rear != self)
        {
            pthread_busy_queue->head = self->next;
            self->next->prev = NULL;
        }
        else
        {
            self->prev ->next = self->next;
            self->next->prev = self->prev;
        }
        self->prev = self->next = NULL;
        pthread_busy_queue->size--;
        pthread_mutex_unlock(&pthread_busy_queue->mutex);

        pthread_mutex_lock(&pthread_leisure_queue->mutex);
        if(pthread_leisure_queue->size==0)
        {
            pthread_leisure_queue->head = self ;
            pthread_leisure_queue->rear = self;
        }
        else
        {
            pthread_leisure_queue->rear ->next = self;
            pthread_leisure_queue->rear = self;
        }
        pthread_leisure_queue->size++;
        pthread_mutex_unlock(&pthread_leisure_queue->mutex);
        pthread_mutex_unlock(&self->mutex);
        pthread_cond_signal(&pthread_leisure_queue->cond);

    }
    
}
void Create_Pthread_Node()
{
    pthread_mutex_lock (&pthread_leisure_queue->mutex);  
    PTHREAD_NODE * temp = NULL;
    PTHREAD_NODE * preTmp = NULL;
    for(int i = 1;i<=PTHREAD_DEF_NUMBER;i++)
    {
        temp = (PTHREAD_NODE *) malloc(sizeof(PTHREAD_NODE));
        if(temp == NULL)
        {
            printf ("malloc failure\n");
            exit (EXIT_FAILURE);
        }
        if(i==1)
            pthread_leisure_queue->head = temp;
        temp->flag = 0;
        temp->prev = preTmp;
        temp->work = NULL;
        pthread_cond_init(&(temp->cond),NULL);
        pthread_mutex_init(&(temp->mutex),NULL);
        temp->prev = preTmp;
        if(preTmp!=NULL)
            preTmp->next = temp;
        pthread_create(&temp->tid,NULL,Pthread_Work,(void *)temp);
        preTmp = temp;
        temp = NULL;
    }
    pthread_leisure_queue->rear = preTmp;
    pthread_leisure_queue->size = PTHREAD_DEF_NUMBER;
    pthread_mutex_unlock(&(pthread_leisure_queue->mutex));
}
void PthreadPool_system_init()
{
    pthread_leisure_queue = (PTHREAD_QUEUE *)malloc(sizeof(PTHREAD_QUEUE));
    pthread_leisure_queue->head = NULL;
    pthread_leisure_queue->rear = NULL;
    pthread_leisure_queue->size = 0;
    pthread_cond_init(&(pthread_leisure_queue->cond),NULL);
    pthread_mutex_init(&(pthread_leisure_queue->mutex),NULL);

    pthread_busy_queue = (PTHREAD_QUEUE *)malloc(sizeof(PTHREAD_QUEUE));
    pthread_busy_queue->size = 0;
    pthread_busy_queue->rear = NULL;
    pthread_busy_queue->head = NULL;
    pthread_cond_init(&(pthread_busy_queue->cond),NULL);
    pthread_mutex_init(&(pthread_busy_queue->mutex),NULL);

    task_NeedWork_queue = (TASK_QUEUE * )malloc(sizeof(TASK_QUEUE));
    task_NeedWork_queue->size = 0;
    task_NeedWork_queue->head = NULL;
    task_NeedWork_queue->rear = NULL;
    pthread_cond_init(&(task_NeedWork_queue->cond),NULL);
    pthread_mutex_init(&(task_NeedWork_queue->mutex),NULL);

    Create_Pthread_Node();
}
void *prcoess_client(void * ptr)
{
    int net_fd;
    net_fd = atoi((char *)ptr);
    char buff[128];
    if(-1 == recv (net_fd, buff, sizeof (buff), 0))
    {
        printf ("recv msg error\n");      
        close (net_fd);
        goto clean;  
    }
    printf("%d\n",syscall (SYS_gettid));
    strcpy(buff,"hello i'm server");
    if(-1==send(net_fd,buff,strlen(buff),0))
    {
        printf ("send msg error\n");      
        close (net_fd);
        goto clean;
    }
    close (net_fd);
    return;
clean:
    sys_clean();
}
void Task_Manager()
{
    int sock_fd;
    sock_fd = socket(AF_INET,SOCK_STREAM,0);
    if(sock_fd==-1)
    {
        perror("listen error");
        goto clean;
    }
    struct sockaddr_in myaddrs;
    memset(&myaddrs,0,sizeof(myaddrs));
    myaddrs.sin_port = htons(POST);
    myaddrs.sin_family = AF_INET;
    myaddrs.sin_addr.s_addr = INADDR_ANY;
    if(-1==(bind(sock_fd,(struct sockaddr *)&myaddrs,sizeof(myaddrs))))
    {
        perror("bind");
        goto clean;
    }
    if (-1 == listen (sock_fd, 5))    
    {      
        perror ("listen");
        goto clean;   
    }
    TASK_NODE * newtask;
    for(int number = 1;;number++)
    {
        int newfd;
        struct sockaddr_in client;
        socklen_t len = sizeof (client);
        if (-1 ==(newfd = accept (sock_fd, (struct sockaddr *) &client, &len)))        
        {  
            perror ("accept");
            goto clean;        
        }
        newtask = (TASK_NODE *) malloc (sizeof (TASK_NODE));
        if (newtask == NULL)        
        {          
            printf ("malloc error");       
            goto clean;        
        }
        newtask->flag = 0;

        newtask->arg = (void *) malloc (128);
        memset (newtask->arg, '\0', 128);
        sprintf (newtask->arg, "%d", newfd);

        newtask->next = NULL;
        newtask->fun = prcoess_client;
        newtask->tid = 0;
        newtask->work_id = number;
        //pthread_cond_init(&(newtask->cond),NULL);
        pthread_mutex_init(&(newtask->mutex),NULL);
        
        pthread_mutex_lock(&(task_NeedWork_queue->mutex));
        if(task_NeedWork_queue->size == 0)
        {
            task_NeedWork_queue->head  = newtask;
            task_NeedWork_queue->rear = newtask;
        }
        else
        {
            task_NeedWork_queue->rear->next = newtask;
            task_NeedWork_queue->rear = newtask;
        }
        task_NeedWork_queue->size++;
        pthread_mutex_unlock(&(task_NeedWork_queue->mutex));
        pthread_cond_signal(&(task_NeedWork_queue->cond));
    }
    return;
clean:
    sys_clean();
}
void Thread_Manager()
{
    PTHREAD_NODE * temp_thread;
    TASK_NODE * temp_task;
    while(1)
    {
        temp_thread = NULL;
        temp_task = NULL;
        pthread_mutex_lock(&(task_NeedWork_queue->mutex));
        if(task_NeedWork_queue->size==0)
            pthread_cond_wait(&(task_NeedWork_queue->cond),&(task_NeedWork_queue->mutex));
        task_NeedWork_queue->size--;
        temp_task = task_NeedWork_queue->head;
        task_NeedWork_queue->head = task_NeedWork_queue->head->next;
        temp_task->next = NULL;
        pthread_mutex_unlock(&(task_NeedWork_queue->mutex));

        pthread_mutex_lock(&(pthread_leisure_queue->mutex));
        if(pthread_leisure_queue->size==0)
            pthread_cond_wait(&(pthread_leisure_queue->cond),&(pthread_leisure_queue->mutex));
        temp_thread = pthread_leisure_queue->head;
        if(pthread_leisure_queue->head==pthread_leisure_queue->rear)
        {
            pthread_leisure_queue->head = NULL;
            pthread_leisure_queue->rear = NULL;
        }
        else
        {
            pthread_leisure_queue->head = pthread_leisure_queue->head->next;
            pthread_leisure_queue->head->prev = NULL;
        }
        pthread_leisure_queue->size--;
        pthread_mutex_unlock(&(pthread_leisure_queue->mutex));

        pthread_mutex_lock(&(temp_thread->mutex));
        temp_thread->flag = 1;
        temp_thread->next = NULL;
        temp_thread->prev =NULL;
        temp_thread->work = temp_task;
        pthread_mutex_unlock(&(temp_thread->mutex));
        
        pthread_mutex_lock(&(pthread_busy_queue->mutex));
        if(pthread_busy_queue->size==0)
        {
            pthread_busy_queue->rear = temp_thread;
            pthread_busy_queue->head = temp_thread;
        }
        else
        {
            pthread_busy_queue->rear->next = temp_thread;
            temp_thread->prev = pthread_busy_queue->rear;
            pthread_busy_queue->rear = temp_thread;
        }
        pthread_busy_queue->size++;
        pthread_mutex_unlock(&(pthread_busy_queue->mutex));
        pthread_cond_signal(&(temp_thread->cond));
        
    }
}


void monitor(void * ptr)
{
    //THREAD_NODE * temp_thread = NULL; 
    int number = 1;
    while (1)    
    {      
        printf("--------------------------------------------\n");
        printf("检测数:%d\n",number);
        pthread_mutex_lock(&(pthread_busy_queue->mutex));
        printf("忙碌线程:%d\n",pthread_busy_queue->size);
        pthread_mutex_unlock(&(pthread_busy_queue->mutex));
        pthread_mutex_lock(&(pthread_leisure_queue->mutex));
        printf("空闲线程:%d\n",pthread_leisure_queue->size);
        pthread_mutex_unlock(&(pthread_leisure_queue->mutex));
        pthread_mutex_lock(&(task_NeedWork_queue->mutex));
        printf("任务数还有:%d\n",task_NeedWork_queue->size);
        pthread_mutex_unlock(&(task_NeedWork_queue->mutex));
        printf("--------------------------------------------\n\n\n");
        number++;
        sleep(1);
    }  
    return;
}
#include"pool.h"

int main()
{
    pthread_t thread_manager_tid, task_manager_tid,monitor_tid;
    PthreadPool_system_init();
    pthread_create(&task_manager_tid,NULL,Task_Manager,NULL);
    pthread_create(&thread_manager_tid,NULL,Thread_Manager,NULL);
    pthread_create(&monitor_tid,NULL,monitor,NULL);
    pthread_join (thread_manager_tid, NULL);
    pthread_join (task_manager_tid, NULL);
    pthread_join(monitor_tid,NULL);
    sys_clean ();
    return 0;

}
#ifndef _MyPthread_pool_
#define _MyPthread_pool_

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include <net/if_arp.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>

#define POST 9005
#define PTHREAD_MAX_NUMBER 50
#define PTHREAD_MIN_NUMBER 5
#define PTHREAD_DEF_NUMBER 20

typedef struct task_node
{
    pthread_t tid;
    //pthread_cond_t cond;
    pthread_mutex_t mutex;
    int flag;                   //1:busy,2:free
    int work_id;
    struct task_node * next;
    void * (*fun)(void *);
    void * arg;
}TASK_NODE;


typedef struct task_queue
{
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    struct task_node * head;
    struct task_node * rear;
    int size;
}TASK_QUEUE;


typedef struct pthread_node
{
    pthread_t tid;
    pthread_cond_t cond;
    pthread_mutex_t mutex;
    struct pthread_node * prev;
    struct pthread_node * next;
    int flag;
    struct task_node * work;
}PTHREAD_NODE;

typedef struct pthread_queue
{
    struct pthread_node * head;
    struct pthread_node * rear;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int size;
}PTHREAD_QUEUE;

extern PTHREAD_QUEUE * pthread_leisure_queue;
extern PTHREAD_QUEUE * pthread_busy_queue;
extern TASK_QUEUE * task_NeedWork_queue;


void sys_clean(void);
void * Pthread_Work(void * ptr);
void Create_Pthread_Node();
void PthreadPool_system_init();
void *prcoess_client(void * ptr);
void Task_Manager();
void Thread_Manager();
void monitor(void * ptr);
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值