Linux 之C++ 线程池

       我想做的就是对每个线程进行有针对性的控制,也即可以对线程进行暂停,恢复,退出等等精细控制,对于此项要求,我的想法是声明一个类,该类中有些精细的操作其中包括该线程的状态,对线程控制的互斥变量(pthread_mutex_t),以及唤醒的条件(pthread_cond_t),要实现这些功能其核心在于,每个线程拥有自己的控制变量,也即线程执行函数是线程类的静态函数,该线程函数的参数是该线程类对象的this指针!!!

class Servant
{
	private:

		pthread_mutex_t mutex_x;
		pthread_cond_t cond_t;
		int state;
	public:
		pthread_t m_tid;
		Servant();
		void start();
	static void* ThreadProc(void* data);
		void notify();
		void stop();
		void wakeup();
		void exit();
		void join();
};
这是该线程类的声明,最主要的是查看ThreadProc静态函数

void* Servant::ThreadProc(void* data)
{    
    Servant* ser=(Servant*)data;
    int result=0;
    while(ser->state!=EXIT)
    {
        while(ser->state==IDLE)
        {
            result=pthread_mutex_lock(&(ser->mutex_x));
            if(0==result)
            {
                printf("waiting for the mutex \n");
            }            
            result=pthread_cond_wait(&(ser->cond_t),&(ser->mutex_x));    
            if(ser->state!=IDLE)
                goto End;
                
            printf("the conditions has been notified\n");
            //we take this thread to busy list
            ser->m_pool->AddtoIdle(false,ser);
            ser->m_pool->Addtobusy(true,ser);
            // really   work
            
            DoSomething:
            ser->state=WORKING;            
            printf("Do Something...\n");
            ser->DoJob();
            ser->Complete();//this function change state
            End:
            pthread_mutex_unlock(&(ser->mutex_x));                    
        }
    }
    return NULL;
}
这函数,主要控制的就两项,其一state,每次对线程状态的改变,都是基于原子线程已经执行完毕的基础上的,也即,核心操作是不能被状态的改变所修改的。每次被唤醒时,都需要进行检测state的值,如果STATE还是RUN,则表明有新的任务要处理,否则表明唤醒只是为了要修改当前线程状态!!!,现在看一下一个API

pthread_cond_wait,该函数调用时首先必须必须由本线程加锁,这个函数需要两个变量一个是mutex_x(加锁的互斥变量)和cond_t(条件变量),在更新条件以前,mutex_x一直保持锁定状态,并在线程挂起进入等待解锁,当执行pthread_cond_singal时,激活互斥变量mutex,并向下执行,当离开pthread_cond_wait时,重新加锁

现Servant.h文件内容如下:

#include<pthread.h>
#include<vector>
using namespace std;
class Servant
{
	private:

		pthread_mutex_t mutex_x;
		pthread_cond_t cond_t;
		int state;
	public:
		pthread_t m_tid;
		Servant();
		void start();
	static void* ThreadProc(void* data);
		void notify();
		void stop();
		void wakeup();
		void exit();
		void join();
};
//ServantPool supposed to be singlton
class ServantPool
{
private:
	vector<Servant*> m_idle_list;
	vector<Servant*> m_busy_list;
	ServantPool(){};
	static ServantPool * hInstance;
public:	
	void TerminateAll();
	void create(int num);
	void start();
	void stop(pthread_t id);
	void wakeup(pthread_t id);
	void waitforAll();
	~ServantPool();	
	static ServantPool * getInstance();	
};


Servant.cpp文件内容如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include"Servant.h"
#define WORKING 1
#define STOP 2
#define EXIT 3
#define IDLE 4
static int num=0;
static     pthread_mutex_t vec_mutex; 
void Servant::start()
{
    state=IDLE;
    int result=pthread_create(&m_tid,NULL,ThreadProc,this);
    if(0!=result)
    {
        printf("thread create result :%s\n",strerror(errno));
    }
}
Servant::Servant(ServantPool* ma)
{    
    thread_id=num++;
    m_pool=ma;    
    pthread_mutex_init(&mutex_x,NULL);
    pthread_cond_init(&cond_t,NULL);    
}
void Servant::setSocket(int m)
{
    m_socket=m;
}
void Servant::DoJob()
{
    char buf[100]={0};
    recv(m_socket,buf,100,0);
    printf("we haved the %d recv:%s\n",num++,buf);
    close(m_socket);
}
void* Servant::ThreadProc(void* data)
{    
    Servant* ser=(Servant*)data;
    int result=0;
    while(ser->state!=EXIT)
    {
        while(ser->state==IDLE)
        {
            result=pthread_mutex_lock(&(ser->mutex_x));
            if(0==result)
            {
                printf("waiting for the mutex \n");
            }            
            result=pthread_cond_wait(&(ser->cond_t),&(ser->mutex_x));    
            if(ser->state!=IDLE)
                goto End;
                
            printf("the conditions has been notified\n");
            //we take this thread to busy list
            ser->m_pool->AddtoIdle(false,ser);
            ser->m_pool->Addtobusy(true,ser);
            // really   work
            
            DoSomething:
            ser->state=WORKING;            
            printf("Do Something...\n");
            ser->DoJob();
            ser->Complete();//this function change state
            End:
            pthread_mutex_unlock(&(ser->mutex_x));                    
        }
    }
    return NULL;
}
void Servant::stop()
{
    if(state==IDLE)        
    {
        m_pool->AddtoIdle(false,this);
        m_pool->Addtostop(true,this);
        state=STOP;
        printf("thread stop!\n");        
    }
    else if(state==WORKING)
    {
        printf("current state is WORKING stop failed!\n");                
    }
    else if(state==STOP)
    {
        printf("thread already stopped!\n");                
    }
    else 
    {
        printf("sorry unknown state!\n");
        state=STOP;
    }
}
void Servant::wakeup()
{
    if(state==STOP)        
    {
        m_pool->Addtostop(false,this);
        m_pool->AddtoIdle(true,this);
        state=IDLE;    
        printf("thread wakeup!\n");            
    }
    else if(state==WORKING)
    {
        printf("current state  is WORKING stop failed!\n");
    }
    else if(state==IDLE)
    {
        printf("current state  is idle never need wakeup!\n");
    }
    else
    {
        printf("sorry unknown state..\n");
        state=IDLE;
    }
}
void Servant::Complete()//完成操作
{
    //完成任务,该线程变为idle        
    m_pool->Addtobusy(false,this);
    m_pool->AddtoIdle(true,this);    
    state=IDLE;
}
void Servant::join()
{
    pthread_join(m_tid,NULL);
}
void Servant::notify()
{
    if(state==IDLE)
    {        
        printf("we have notified thread running\n");
        pthread_cond_signal(&cond_t);    
    }
    else
    {
        printf("sorry ,the signal is not correct\n");
    }
}
void Servant::exit()
{
    state=EXIT;
    pthread_cond_signal(&cond_t);    
}




void ServantPool::StopAll()
{    
    vector<Servant*>::iterator itr=m_idle_list.begin();    
    for(;itr!=m_idle_list.end();)
    {
        (*itr)->stop();        
    }
    itr=m_busy_list.begin();
    for(;itr!=m_busy_list.end();)
    {
        (*itr)->stop();        
    }    
}
void ServantPool::create(int num)
{
    int i=0;
    for(;i<num;i++)
    {
        Servant* tmp=new Servant(this);
        m_idle_list.push_back(tmp);
    }
}
void ServantPool::AddtoIdle(bool add,Servant* ser)
{
    if(add)
    {
        // add ser to idle list
        pthread_mutex_lock(&vec_mutex);
        m_idle_list.push_back(ser);
        pthread_mutex_unlock(&vec_mutex);
    }
    else
    {
        // del ser from idle list
        pthread_mutex_lock(&vec_mutex);
        vector<Servant*>::iterator itr=m_idle_list.begin();
        for(;itr!=m_idle_list.end();itr++)
        {
            if(*itr==ser)
            {
                m_idle_list.erase(itr);
                break;
            }
        }
        pthread_mutex_unlock(&vec_mutex);
    }
}
void ServantPool::Addtobusy(bool add,Servant* ser)
{
    if(add)
    {
        // add ser to idle list
        pthread_mutex_lock(&vec_mutex);
        m_busy_list.push_back(ser);
        pthread_mutex_unlock(&vec_mutex);
    }
    else
    {
        // del ser from idle list
        pthread_mutex_lock(&vec_mutex);
        vector<Servant*>::iterator itr=m_busy_list.begin();
        for(;itr!=m_busy_list.end();itr++)
        {
            if(*itr==ser)
            {
                m_busy_list.erase(itr);
                break;
            }
        }
        pthread_mutex_unlock(&vec_mutex);
    }
}
void ServantPool::Addtostop(bool add,Servant* ser)
{
    if(add)
    {
        // add ser to idle list
        pthread_mutex_lock(&vec_mutex);
        m_stop_list.push_back(ser);
        pthread_mutex_unlock(&vec_mutex);
    }
    else
    {
        // del ser from idle list
        pthread_mutex_lock(&vec_mutex);
        vector<Servant*>::iterator itr=m_stop_list.begin();
        for(;itr!=m_stop_list.end();itr++)
        {
            if(*itr==ser)
            {
                m_stop_list.erase(itr);
                break;
            }
        }
        pthread_mutex_unlock(&vec_mutex);
    }
}
void ServantPool::startAll()
{
    int i=0;
    for(;i<m_idle_list.size();i++)
    {
        Servant* tmp=m_idle_list[i];
        printf("start the thread %d\n",i);
        tmp->start();//create the thread
    }
}

void ServantPool::stop(Servant* id)
{    
    vector<Servant*>::iterator itr=m_idle_list.begin();    
    for(;itr!=m_idle_list.end();itr++)
    {
        if((*itr)==id)
        {    
            (*itr)->stop();            
            return;
        }
    }
}

void ServantPool::waitforAll()
{
    int i=0;
    int nums=m_busy_list.size();
    for(;i<nums;i++)
    {            
        Servant* tmp=m_busy_list[i];
        tmp->join();
    }
    nums=m_idle_list.size();
    i=0;
    for(;i<nums;i++)
    {            
        Servant* tmp=m_idle_list[i];
        tmp->join();
    }    
}

void ServantPool::wakeup(Servant* id)
{    
    vector<Servant*>::iterator itr=m_busy_list.begin();    
    for(;itr!=m_busy_list.end();itr++)
    {
        if((*itr)==id)
        {    
            (*itr)->wakeup();            
            return;
        }
    }
}
ServantPool * ServantPool::hInstance=NULL;
ServantPool * ServantPool::getInstance()
{    
    if(NULL==hInstance)
    {
        hInstance=new ServantPool();
        pthread_mutex_init(&vec_mutex,NULL);
    }
    return hInstance;        
}
ServantPool::~ServantPool()
{
    vector<Servant*>::iterator itr=m_idle_list.begin();
    for(;itr!=m_idle_list.end();)
    {        
        (*itr)->exit();                
        delete *itr;        
        itr=m_idle_list.erase(itr);        
    }
    
    itr=m_busy_list.begin();
    for(;itr!=m_busy_list.end();)
    {        
        (*itr)->exit();                
        delete *itr;        
        itr=m_busy_list.erase(itr);        
    }    
    
    itr=m_stop_list.begin();
    for(;itr!=m_stop_list.end();)
    {        
        (*itr)->exit();                
        delete *itr;        
        itr=m_stop_list.erase(itr);        
    }    
}
Servant* ServantPool::Accepting()
{
    if(m_idle_list.size()>0)
    {
        return m_idle_list[0];
    }
    return NULL;
}



main.c文件如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include"Servant.h"
//create 100 servants thread
#define SERVANT_NUM 1
int main()
{

	ServantPool *mm=ServantPool::getInstance();
	printf("we begin create %d Servant threads \n",SERVANT_NUM);
	mm->create(SERVANT_NUM);
	mm->start();
	mm->waitforAll();
	return 0;
}

makefile文件内容如下:

test:Servant.o main.o
	g++ -o   test Servant.o main.o  -lpthread
Servant.o:Servant.cpp Servant.h
	g++ -g -c  Servant.cpp -lpthread
main.o:main.c Servant.h   
	g++ -g -c  main.c -lpthread
clean:
	rm *.o test

这里面需要注意一点,就是,在修改线程状态时,首先应该修改的是线程状态值,然后才继续进行信号通知,这样可以避免,当信号通知时,状态值还没有发生变化!!!

信号修改失败。好了,这就是暂时要表达的线程池的内容了,如有错误,该请大神指正


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的基于线程池的快速排序实现,使用了 pthread 库和 C++11 的标准库: ```c++ #include <iostream> #include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> std::mutex mtx; std::condition_variable cv; std::queue<std::function<void()>> tasks; std::vector<std::thread> threads; void sort(std::vector<int>& v, int left, int right) { if (left < right) { int pivot = v[left]; int i = left + 1; int j = right; while (i <= j) { if (v[i] <= pivot) { ++i; } else if (v[j] > pivot) { --j; } else { std::swap(v[i], v[j]); } } std::swap(v[left], v[j]); sort(v, left, j - 1); sort(v, j + 1, right); } } void worker() { while (true) { std::function<void()> task; { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{ return !tasks.empty(); }); task = tasks.front(); tasks.pop(); } task(); } } int main() { const int num_threads = 4; for (int i = 0; i < num_threads; ++i) { threads.emplace_back(worker); } std::vector<int> v = {4, 6, 2, 8, 5, 7, 1, 9, 3}; int n = v.size(); std::function<void()> task = [&]{ sort(v, 0, n - 1); }; { std::unique_lock<std::mutex> lock(mtx); tasks.emplace(task); } cv.notify_one(); for (auto& t : threads) { t.join(); } for (int x : v) { std::cout << x << " "; } std::cout << std::endl; return 0; } ``` 该程序中,我们首先定义了一个线程池,使用了一个条件变量 cv 和一个互斥锁 mtx 来实现线程间的同步和通信。 然后定义了一个 worker 函数,该函数会不断从任务队列中取出任务并执行,直到程序结束。 在主函数中,我们创建了 num_threads 个线程,并将它们的执行函数设置为 worker。然后创建了一个需要排序的数组 v,并定义了一个任务 task,该任务将对数组进行快速排序。 接着,我们将任务加入到任务队列中,并使用条件变量 cv 来通知一个线程可以开始执行任务了。由于我们只有一个任务,因此只需要通知一个线程即可。 最后,我们等待所有线程执行完毕,输出排序后的数组。 注意这里的实现使用了 C++11 的标准库,如果你使用的是 C 语言,可以使用类似的 POSIX 线程库来实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世纪殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值