线程池
线程池的概念:因为创建线程池需要一定时间和分配资源。在网络I/O处理单元中,为了提高服务器响应的速度我们利用I/O多路复用(select、poll、epoll)来处理客户连接,当有一个客户连接到来时,减少客户端的等待时间,利用主线程区监听sockfd,之后将监听到的sockfd分配给子线程去处理,但是我们不可能有一个连接就创建并分配一个子线程给这个sockfd,因为这是消耗系统资源的。所以我们可以预先创建线程池。设计到线程池就要涉及到加锁、解锁、信号量(主要是用来判断有多少个空闲的线程)。
代码部分:
/*此文件是用来作为线程池使用,文件名:threadpool.h*/
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include<list>
#include<cstdio>
#include<exception>
#include<pthread.h>
#include "locker.h"
template<typename T>
class threadpool
{
public:
threadpool(int thread_number=8,int max_requests=1000);
~threadpool();
bool append(T* request);
private:
/*工作线程*/
static void* worker(void* arg);
void run();
private:
int m_thread_number; //线程数量
int m_max_requests; //最大处理数
pthread_t* m_threads; //线程指针
std::list<T*> m_workqueue; //请求对列
locker m_queuelocker; //线程锁
sem m_queuestat; //信号量
bool m_stop; //是否让线程停下来
};
template<typename T>
threadpool<T>::threadpool(int thread_number,int max_requests):
m_thread_number(thread_number),m_max_requests(max_requests),m_stop(false),m_threads(NULL)
{
if((thread_number<=0)||(max_requests<=0))
{
/*如果线程数量小于等于0或者最大请求数也小于等于0则抛出异常*/
throw std::exception();
}
/*创建线程*/
m_threads = new pthread_t[m_thread_number];
if(!m_threads)
{
throw std::exception();
}
for(int i=0;i<thread_number;i++)
{
printf("create the %dth pthread\n",i);
if(pthread_create(m_threads+i,NULL,worker,this)!=0)
{
/*创建失败则删除指针并抛出异常*/
delete [] m_threads;
throw std::exception();
}
/*分离线程,分离失败,删除指针和抛出异常*/
if(pthread_detach(m_threads[i]))
{
delete [] m_threads;
throw std::exception();
}
}
}
template<typename T>
threadpool<T>::~threadpool()
{
delete [] m_threads;
m_stop=true;
}
/*创建任务队列*/
template<typename T>
bool threadpool<T>::append(T* request)
{
m_queuelocker.lock(); /*因为任务对列是所有线程共享的,所以要加锁*/
/*任务对列的最大长度超过了要求的最大长度则表示不能再插入任务了,创建任务失败*/
if(m_workqueue.size()>m_max_requests)
{
m_queuelocker.unlock();
return false;
}
/*插入任务对列*/
m_workqueue.push_back(request);
/*解锁,信号量加1*/
m_queuelocker.unlock();
m_queuestat.post();
return true;
}
template<typename T>
void* threadpool<T>::worker(void *arg)
{
threadpool* pool = (threadpool*)arg;//强制转换类型
pool->run();
return pool;
}
template<typename T>
void threadpool<T>::run()
{
while(!m_stop)
{
m_queuestat.wait(); //等待信号量
m_queuelocker.lock(); //等待锁
if(m_workqueue.empty())
{
/*任务对列为空*/
m_queuelocker.unlock();
continue;
}
T* request = m_workqueue.front();//取出一个任务
m_workqueue.pop_front();
m_queuelocker.unlock();
if(!request)
{
continue;
}
request->process();
}
}
#endif
1、下面创建locker.h代码:
/*此文件为locker.h*/
#ifndef LOCKER_H
#define LOCKER_H
#include <exception>
#include <pthread.h>
#include <semaphore.h>
class sem
{
public:
sem()
{
if( sem_init( &m_sem, 0, 0 ) != 0 )
{
throw std::exception();
}
}
~sem()
{
sem_destroy( &m_sem );
}
bool wait()
{
return sem_wait( &m_sem ) == 0;
}
bool post()
{
return sem_post( &m_sem ) == 0;
}
private:
sem_t m_sem;
};
class locker
{
public:
locker()
{
if( pthread_mutex_init( &m_mutex, NULL ) != 0 )
{
throw std::exception();
}
}
~locker()
{
pthread_mutex_destroy( &m_mutex );
}
bool lock()
{
return pthread_mutex_lock( &m_mutex ) == 0;
}
bool unlock()
{
return pthread_mutex_unlock( &m_mutex ) == 0;
}
private:
pthread_mutex_t m_mutex;
};
class cond
{
public:
cond()
{
if( pthread_mutex_init( &m_mutex, NULL ) != 0 )
{
throw std::exception();
}
if ( pthread_cond_init( &m_cond, NULL ) != 0 )
{
pthread_mutex_destroy( &m_mutex );
throw std::exception();
}
}
~cond()
{
pthread_mutex_destroy( &m_mutex );
pthread_cond_destroy( &m_cond );
}
bool wait()
{
int ret = 0;
pthread_mutex_lock( &m_mutex );
ret = pthread_cond_wait( &m_cond, &m_mutex );
pthread_mutex_unlock( &m_mutex );
return ret == 0;
}
bool signal()
{
return pthread_cond_signal( &m_cond ) == 0;
}
private:
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
};
#endif
下面是worker.h代码
#ifndef WORKER_H
#define WORKER_H
#include<stdio.h>
class Worker
{
public:
Worker(){};
void process()
{
int sum=0;
for(int i=0;i<10;i++)
{
sum += i;
}
printf("sum=%d\n",sum);
}
};
#endif
下面是主函数
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include "locker.h"
#include "worker.h"
#include "threadpool.h"
int main()
{
Worker* work = new Worker[8];
threadpool< Worker >* pool =new threadpool< Worker >;
//pool = ;
for(int i=0;i<8;i++){
pool->append(work+i);
}
sleep(1000000);//给线程一定的运行时间
}