线程池概念:一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。
应用场景:1、需要大量的线程来完成任务,且完成任务的时间比较短;2、对性能要求苛刻的应用;3、接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用
不使用线程池的情况:若是一个数据请求的到来伴随一个线程去创建,就会产生一定的风险以及一些不必要的消耗。
1、线程若不限制数量的创建,在峰值压力下,线程创建过多,资源耗尽,有程序崩溃的风险;
2、处理一个短时间任务时,会有大量的资源用于线程的创建与销毁成本上。
功能:线程池是使用了已经创建好的线程进行循环处理任务,避免了大量线程的频繁创建与销毁的时间成本
如何实现一个线程池
线程池 = 大量线程 + 任务缓冲队列
困难与解决方案:在创建线程时,都是伴随创建线程的入口函数,一旦创建就无法改变,导致线程池进行任务处理的方式过于单一,灵活性太差。若任务队列中的任务,不仅仅是单纯的数据,而是包含处理任务方法在内的数据,这时候,线程池的线程是一条普通的执行流,只需要使用传入的方法去处理数据即可。这样子就可以提高线程池的灵活性
代码实现流程:定义一个任务类Task
,成员变量有要处理的数据_data
和处理数据的方法_handler
。成员函数有设置要处理数据和处理方式的函数setTask
,还有一个处开始处理数据的函数run
(创建线程时传入的方法,由于创建线程必须有入口函数,这里用run封装所有的处理方式,让所有线程都将run置为入口函数,就提高了线程池的灵活性)。再定义一个线程池类ThreadPool
,成员变量有定义线程池中线程的最大数量thr_max
,一个任务缓冲队列_queue
,一个互斥量_mutex
,用于实现对缓冲队列的安全性,一个条件变量_cond
,用于实现线程池中线程的同步。
threadpool.hpp文件
//threadpool.hpp
#include <iostream>
#include <cstdio>
#include <queue>
#include <stdlib.h>
#include <pthread.h>
using namespace std;
typedef void (*handler_t)(int);
#define MAX_THREAD 5
//任务类
class ThreadTask
{
public:
ThreadTask()
{
}
//将数据与处理方式打包在一起
void setTask(int data, handler_t handler)
{
_data = data;
_handler = handler;
}
//执行任务函数
void run()
{
return _handler(_data);
}
private:
int _data;//任务中处理的数据
handler_t _handler;//处理任务方式
};
//线程池类
class ThreadPool
{
public:
ThreadPool(int thr_max = MAX_THREAD)
:_thr_max(thr_max)
{
pthread_mutex_init(&_mutex, NULL);
pthread_cond_init(&_cond, NULL);
for (int i = 0; i < _thr_max; i++)
{
pthread_t tid;
int ret = pthread_create(&tid, NULL, thr_start, this);
if (ret != 0)
{
printf("thread create error\n");
exit(-1);
}
}
}
~ThreadPool()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond);
}
bool taskPush(ThreadTask &task)
{
pthread_mutex_lock(&_mutex);
_queue.push(task);
pthread_mutex_unlock(&_mutex);
pthread_cond_signal(&_cond);
return true;
}
//类的成员函数,有默认的隐藏参数this指针
//置为static,没有this指针,
static void *thr_start(void *arg)
{
ThreadPool *p = (ThreadPool*)arg;
while (1)
{
pthread_mutex_lock(&p->_mutex);
while (p->_queue.empty())
{
pthread_cond_wait(&p->_cond, &p->_mutex);
}
ThreadTask task;
task =p-> _queue.front();
p->_queue.pop();
pthread_mutex_unlock(&p->_mutex);
task.run();//任务的处理要放在解锁之外
}
return NULL;
}
private:
int _thr_max;//线程池中线程的最大数量
queue<ThreadTask> _queue;//任务缓冲队列
pthread_mutex_t _mutex; //保护队列操作的互斥量
pthread_cond_t _cond; //实现从队列中获取结点的同步条件变量
};
main.cpp
//main.cpp
#include <unistd.h>
#include "threadpool.hpp"
//处理方法1
void test_func(int data)
{
int sec = (data % 3) +1;
printf("tid:%p -- get data:%d, sleep:%d\n", pthread_self(), data, sec);
sleep(sec);
}
//处理方法2
void tmp_func(int data)
{
printf("tid:%p -- tmp_func\n", pthread_self());
sleep(1);
}
int main()
{
ThreadPool pool;
for (int i = 0; i < 10; i++)
{
ThreadTask task;
if (i % 2 == 0)
{
task.setTask(i, test_func);
}
else
{
task.setTask(i, tmp_func);
}
pool.taskPush(task);
}
sleep(1000);
return 0;
}
运行结果:线程池最多有5个线程,标注的每种颜色对应的是同一个线程,这样子就能完成通过几个线程,完成多个任务,而不是多个线程完成多个任务。创建和销毁的时间开销也节省了不少
转载:https://blog.csdn.net/qq_44443986/article/details/115441456