线程池的优点:
1:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
2:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
3:提高线程的可管理性。
多线程函数
pthread_create函数 创建一个新线程。
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
参数1:传出参数,保存系统为我们分配好的线程ID
参数2:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。
参数3:函数指针,指向线程主函数(线程体),该函数运行结束,则线程结束。
参数4:线程主函数执行期间所使用的参数,如要传多个参数, 可以用结构封装。
reactor模式中:主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,有的话立即通知工作线程(逻辑单元 ),读写数据、接受新连接及处理客户请求均在工作线程中完成。通常由同步I/O实现。
proactor模式中:主线程和内核负责处理读写数据、接受新连接等I/O操作,工作线程仅负责业务逻辑,如处理客户请求。通常由异步I/O实现。
*/
———————————————————————————————————————
pthread_t *m_threads;
if (pthread_create(m_threads + i, NULL, worker, this) != 0)//线程的主函数为worker,传入自身
{
delete[] m_threads;
throw std::exception();
}
void *threadpool<T>::worker(void *arg)
{
threadpool *pool = (threadpool *)arg;
pool->run();//调用线程的执行函数
return pool;
}
void threadpool<T>::run()
{
while (true)
{
m_queuestat.wait();//阻塞线程 等待http连接
m_queuelocker.lock();
if (m_workqueue.empty())
{
m_queuelocker.unlock();
continue;
}
T *request = m_workqueue.front();//T为 http_conn
m_workqueue.pop_front();
m_queuelocker.unlock();
if (!request)
continue;
if (1 == m_actor_model) //m_actor_model 0为proactor 1为reactor
{
if (0 == request->m_state) //当有用户传输0为读 传输1为写
{
if (request->read_once()) //当http中有数据可读时
{
request->improv = 1;
connectionRAII mysqlcon(&request->mysql, m_connPool); //获得http内的数据库连接
request->process();//处理数据 根据http请求报文作出 回报文
}
else
{
request->improv = 1; //improv 和 timer_flag都为处理过后的标志
request->timer_flag = 1;//没有数据可读时,删除定时器
}}
else
{
if (request->write())// 是否可以写
{
request->improv = 1;
}
else //没数据写
{
request->improv = 1;
request->timer_flag = 1;
}}}
else
{
connectionRAII mysqlcon(&request->mysql, m_connPool);
request->process(); //将m_socketfd改为EPOLLIN
} }}
int pthread_detach(pthread_t thread); 成功:0;失败:错误号
线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后,其退出状态不由其他线程获取,而直接自己自动释放。在线程被分离后,不能使用pthread_join等待它的终止状态。进程若有该机制,将不会产生僵尸进程。僵尸进程的产生主要由于进程死后,大部分资源被释放,一点残留资源仍存于系统中,导致内核认为该进程仍存在。也可使用 pthread_create函数参2(线程属性)来设置线程分离。
—————————————————————————————————————
if (pthread_detach(m_threads[i]))//线程自动释放
{
delete[] m_threads;
throw std::exception();
}
线程池的存储
**使用链表存储,方便插入
bool threadpool<T>::append(T *request, int state) //线程存储
{
m_queuelocker.lock(); //互斥锁保证线程同步
if (m_workqueue.size() >= m_max_requests)
{
m_queuelocker.unlock();
return false;
}
request->m_state = state;//0为读取 1为写入操作
m_workqueue.push_back(request);
m_queuelocker.unlock();
m_queuestat.post(); //通知线程来获取资源
return true;
}
总结:线程池模块使用一个链表让主线程与工作线程分开,主线程负责插入资源,工作线程负责竞争获取资源并且执行任务。