c++简易线程池

以前做均衡负载的时候就想写过线程池,那时候没有很理解就没写,最近尝试自己搭个高并发的小型服务器,又学习了下线程池,但感觉网上的大多涉及的技术点比较多,对于初学者不容易理解,这里我也分享下我自己写的简易线程池,调试环境在Ubuntu18.04。
在这里插入图片描述
该线程池通过设置任务函数(搬运工)不断地访问等待队列,让所有子线程均执行该任务函数,只要有任务就取出执行。新增的任务以函数+参数的形式封装推入任务队列。当要销毁线程池时,将队列容量置零并等待所有任务完成即销毁线程数组。
该线程池的特点是简单易用,线程无需频繁创建销毁的开销,但为便于理解没有做安全性封装。
以下直接芳代码,注释比较详细,应该很容易理解。

//thread.h
#ifndef THREAD_H_
#define THREAD_H_

#include <pthread.h>
#include <queue>
#include <semaphore.h>
using namespace std;

typedef void (*pfunc)(void* );    //定义函数指针pfunc

struct pf   //封装函数指针与参数
{
    pfunc fun; 
    void* arg;
};

class thread_pool
{
private:
    sem_t m_sem;   //信号量
    pthread_mutex_t m_mutex1;  //锁1
    pthread_mutex_t m_mutex2;  //锁2
    int max_thread;   //线程数量
    int busy_thread;  //在忙线程数量
    int busy_task;    //未完成任务数量

    queue<pf> wait_queue;   //等待任务队列
    int max_wait;   //队列上限
    pthread_t* thread_arr;      //线程数组
    static void* worker(void* arg);  //与pthread_create进行类型匹配,其中static必要
public:
    thread_pool(int m_th,int w_th); 
    ~thread_pool();
    bool add_task(pfunc pfc,void* arg);  //添加任务
    void close_pool();       //关闭线程池
};
#endif

//thread.cpp
#include <iostream>
#include "thread.h"
using namespace std;

 void* thread_pool::worker(void* arg)    //工作线程
 {
     thread_pool* p=(thread_pool*) arg;    //将传入的对象转化类型
     while(1)
     {
        sem_wait(&p->m_sem);    //如果任务队列无任务,信号量为0,阻塞线程
        pthread_mutex_lock(&p->m_mutex1);   //以下领取任务,防止竞争 
        if(p->wait_queue.empty())   //确保有任务可领取
        {
            cout<<"任务丢失"<<endl;
            pthread_mutex_unlock(&p->m_mutex1);
            continue;
        } 
        p->busy_thread++;  //忙线程+1
        struct pf tmp=p->wait_queue.front();   
        p->wait_queue.pop();   //取出任务
        pthread_mutex_unlock(&p->m_mutex1);
        tmp.fun(tmp.arg);    //执行任务,这里一般不进行阻塞
        pthread_mutex_lock(&p->m_mutex2);   //防止竞争
        p->busy_thread--;   //忙线程-1
        p->busy_task--;  //忙任务-1
        cout<<"完成任务"<<endl;
        pthread_mutex_unlock(&p->m_mutex2);
     }
 };

thread_pool::thread_pool(int m_th,int w_th):max_thread(m_th),busy_thread(0),max_wait(w_th),busy_task(0)
{
    thread_arr=new pthread_t[max_thread];   //创建线程数组
    pthread_mutex_init(&m_mutex1,NULL);  //初始化2把线程锁
    pthread_mutex_init(&m_mutex2,NULL);  
    sem_init(&m_sem,0,0);  //初始化信号量
    for(int i=0;i<max_thread;i++){    //创建线程并分离线程,线程各自执行
        pthread_create(thread_arr+i,NULL,worker,this);
        pthread_detach(thread_arr[i]);
    }   
};

thread_pool::~thread_pool()
{
    if (thread_arr)delete []thread_arr;  //销毁线程数组
}

bool thread_pool::add_task(pfunc pfc,void* arg)
{
    pthread_mutex_lock(&m_mutex1);    //添加任务,防止竞争
    if(wait_queue.size()<max_wait)     //等待队列还未满
    {
        pf newpf={fun:pfc,arg:arg};
        wait_queue.push(newpf);   //将任务函数与参数加入
        busy_task++; 
        pthread_mutex_unlock(&m_mutex1);
        sem_post(&m_sem);   //任务增加,信号量+1
        return true;
    }
    cout<<"队列已满"<<endl;
    pthread_mutex_unlock(&m_mutex1);
    return false;
};

void thread_pool::close_pool()
{
    max_wait=0;   //不允许再添加任务
    while(busy_task>0);   //等待知道任务全都处理完
}
//main.cpp
#include <iostream>
#include "thread.h"
using namespace std;

void work1(void* arg)
{
    int n=*(int*) arg;
    int sum=0;
    for(int i=0;i<1000*n;i++)
    {
        sum+=i;
    }
    printf("%d",sum);
}

int main()
{
    thread_pool tp(4,5);   //创建线程数4,队列长度5的线程池
    int tmp[10];
    for(int i=0;i<10;i++)
    {
        tmp[i]=i;
        tp.add_task(work1,tmp+i);    //连续添加10次任务
    }
    tp.close_pool();
    return 0;
}
//Makefile
FLAG = ${F}
main: main.cpp thread.cpp
	g++ main.cpp thread.cpp -o main ${FLAG} -lpthread

如果有问题与改进的地方也希望小伙伴们指正!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值