c++线程池

线程池的作用,大家都比较清楚,节省了创建和销毁线程带来的开销。

.h文件

#ifndef __THREAD_H  
#define __THREAD_H  

 
#include <deque>
#include <string>  
#include <pthread.h>  
  
using namespace std;  
  
/** 
 * 执行任务的类,设置accept()描述符并执行 
 */  
class CTask {
protected:
    string m_strTaskName;   //任务的名称
    int connfd;    //接收的地址
 
public:
    CTask() = default;
    CTask(string &taskName): m_strTaskName(taskName), connfd(NULL) {}
    virtual int Run() = 0;
    void SetConnFd(int data);   //设置接收的套接字连接号。
    int GetConnFd();
    virtual ~CTask() {}
    
};
 
 
 
 
/** 
 * 线程池类的实现 
 */  
class CThreadPool  
{  
private:  
    static  deque<CTask*> m_deqTaskList;     /** 任务队列 */  
    static  bool shutdown;                    /** 线程退出标志 */           
    int     m_iThreadNum;                     /** 线程池中启动的线程数 */  
    pthread_t   *pthread_id;  
      
    static pthread_mutex_t m_pthreadMutex;    /** 线程同步锁 */  
    static pthread_cond_t m_pthreadCond;      /** 线程同步的条件变量 */  
  
protected:  
    static void* ThreadFunc(void * threadData); /** 新线程的线程回调函数 */  
    static int MoveToIdle(pthread_t tid);       /** 线程执行结束后,把自己放入到空闲线程中 */  
    static int MoveToBusy(pthread_t tid);       /** 移入到忙碌线程中去 */  
      
    int Create();          /** 创建线程池中的线程 */  
  
public:  
    CThreadPool(int threadNum = 10);  
    int AddTask(CTask *task);      /** 把任务添加到任务队列中 */  
    int StopAll();                 /** 使线程池中的线程退出 */  
    int getTaskSize();             /** 获取当前任务队列中的任务数 */  
};  
  
#endif  

.cpp文件

#include "Thread.h"  
#include <iostream>  
#include <stdio.h> 
#include <deque>
 
 
void CTask::SetConnFd(int data)  
{  
    connfd = data;  
}  
 
int CTask::GetConnFd()
{
    return connfd;
}
/**
* 初始化数据
*/
deque<CTask*> CThreadPool::m_deqTaskList;         //任务列表  
bool CThreadPool::shutdown = false;  
      
pthread_mutex_t CThreadPool::m_pthreadMutex = PTHREAD_MUTEX_INITIALIZER;   
pthread_cond_t CThreadPool::m_pthreadCond = PTHREAD_COND_INITIALIZER;  
  
/** 
 * 线程池管理类构造函数 
 */  
CThreadPool::CThreadPool(int threadNum)  
{  
    this->m_iThreadNum = threadNum;  
    cout << "I will create " << threadNum << " threads" << endl;  
    Create();       //*创建对象时便创建线程。
}
 
 
/** 
 * 线程回调函数 
 */  
void* CThreadPool::ThreadFunc(void* threadData)  
{  
    pthread_t tid = pthread_self();  
    while (1)  
    {  
 
        //* 线程开启时先上锁 */
        pthread_mutex_lock(&m_pthreadMutex);  
        while (m_deqTaskList.size() == 0 && !shutdown)  
        {  
            //* 没有任务时,线程等待状态(条件变量)*/
            pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex);  
        }  
          
        if (shutdown)  
        {  
            pthread_mutex_unlock(&m_pthreadMutex);  
            printf("thread %lu will exit\n", pthread_self());  
            pthread_exit(NULL);   
        }  
          
        printf("tid %lu run\n", tid);  
            
        /** 
        * 取任务队列并处理之 
        */ 
 
        //deque<CTask*>::iterator iter = m_deqTaskList.front();
        CTask* task = m_deqTaskList.front();  
        m_deqTaskList.pop_front();
 
        //* 取完任务后释放锁*/
        pthread_mutex_unlock(&m_pthreadMutex);  
          
        task->Run(); /** 执行任务 */  
         
    }  
    return (void*)0;  
}  
 
 
 
 
 
/** 
 * 往任务队列里边添加任务并发出线程同步信号 
 */  
int CThreadPool::AddTask(CTask *task)  
{  
    pthread_mutex_lock(&m_pthreadMutex);  
    this->m_deqTaskList.push_back(task);  
    pthread_mutex_unlock(&m_pthreadMutex); 
 
    // * 添加任务 条件变量发信号,非阻塞  */
    pthread_cond_signal(&m_pthreadCond);       
    return 0;  
}  
  
/** 
 * 创建线程 
 */  
int CThreadPool::Create()  
{  
    pthread_id = (pthread_t*)malloc(sizeof(pthread_t) * m_iThreadNum);  
    for(int i = 0; i < m_iThreadNum; i++)  
    {  
        pthread_create(&pthread_id[i], NULL, ThreadFunc, NULL);  
    }  
    return 0;  
}  
 
 
 
 
 
/** 
 * 停止所有线程 
 */  
int CThreadPool::StopAll()  
{  
    /** 避免重复调用 */  
    if (shutdown)  
    {  
        return -1;    
    }  
    printf("Now I will end all threads!!\n");  
    /** 唤醒所有等待线程,线程池要销毁了 */  
    shutdown = true;  
    pthread_cond_broadcast(&m_pthreadCond);  
      
    /** 阻塞等待线程退出,否则就成僵尸了 */  
    for (int i = 0; i < m_iThreadNum; i++)  
    {  
        pthread_join(pthread_id[i], NULL);    
    }  
      
    free(pthread_id);  
    pthread_id = NULL;  
      
    /** 销毁条件变量和互斥体 */  
    pthread_mutex_destroy(&m_pthreadMutex);  
    pthread_cond_destroy(&m_pthreadCond);  
      
    return 0;  
}  
 
 
 
 
/** 
 * 获取当前队列中任务数 
 */  
int CThreadPool::getTaskSize()  
{  
    return m_deqTaskList.size();      
}  
 
 
 
 
 
 
 

当客户端传递消息时,将消息放入队列中,服务端得知有任务,调用线程池中的线程执行任务。

服务端

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <pthread.h>
#include <assert.h>
#include "Thread.h"
//#include "BookInfo.h"
//#include "StrInfo.h"
 
class CMyTask: public CTask 
{   
 public:
    CMyTask() = default;    
    int Run()
    {
        //printf("%s\n", (char*)m_ptrData);
        //int x = rand()%4 + 1;
        //sleep(x);   
        //return 0;
        
        int connfd= GetConnFd();
        while(1)
        {
            char recvbuf[1024];
            char sendbuf[1024];
           // Book book= new Book;
            
            //BookInfo bf=book.find_book("茶花女");
            //sprintf(sendbuf,"res: %d,%s",bf.book_no,bf.book_name);
            
            memset(recvbuf,0x00,sizeof(recvbuf));
            memset(sendbuf,0x00,sizeof(sendbuf));
            
            //printf("function run test.\n");
            int len = recv(connfd,recvbuf,sizeof(recvbuf),0);
            if(len <= 0)
                printf("no buf.\n");
            printf("%s \n",recvbuf);
            printf("Please input: ");
            fflush(stdout);
            fgets(sendbuf,1024,stdin);
            if(strncmp(sendbuf,"end",3)==0)  
            {  
                close(connfd);  
                break;  
            }  
            send(connfd,sendbuf,sizeof(sendbuf),0);
                    
        }
        close(connfd);
        return 0;
    }
};
 
 
 
 
 
int main(int argc, char* argv[])
{
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd!=-1);
    struct sockaddr_in ser,cli;
    memset(&ser,0,sizeof(ser));
    ser.sin_family=AF_INET;
    inet_aton("127.0.0.1",&ser.sin_addr);
    ser.sin_port=htons(6500);
 
    int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
    assert(res!=-1);
 
    listen(sockfd,5);
    //创建线程池
    CThreadPool Pool(5);
 
    //for(int i=0;i<5;i++)
    //{
      // Task* ta=new Task;
       //Pool.AddTask(ta);
    //}
    
    while(1)
    {
       socklen_t len=sizeof(cli);
       int connectfd=accept(sockfd,(struct sockaddr*)&cli,&len);
       if(connectfd<0)
       {
           printf("cli connect failed.");
          // throw  std::exception();
       
       }
       //收到客户端请求,即添加到任务队列去
       else
       {
           CTask* ta=new CMyTask;
           ta->SetConnFd(connectfd);
           Pool.AddTask(ta);
       }
      
      
      
    }
    close(sockfd);
    return 0;
 
    
}
 
 
 

客户端

#include<iostream>
#include<stdio.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<string.h>
 
int main()
{
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    // assert(sockfd!=-1);
   
     struct sockaddr_in ser,cli;
     memset(&ser,0x00,sizeof(ser));
     ser.sin_family=AF_INET;
     inet_aton("127.0.0.1",&ser.sin_addr);
     ser.sin_port=htons(6500);
 
 
    int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));  
   //assert(res!=-1); 
 
    while(1)
   {
        printf("please input:");  
        fflush(stdout);  
        char buff[128]={0};  
        fgets(buff,128,stdin);
        //std::cin>>buff;
        if(strncmp(buff,"end",3)==0)  
        {  
            close(sockfd);  
            break;  
        }  
        send(sockfd,buff,strlen(buff)-1,0);  
        memset(buff,0,128);  
        recv(sockfd,buff,127,0);  
        printf("%s\n",buff); 
       
   }
   close(sockfd);
   return 0;
 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值