池化技术一直是一种高效的技术,我们都知道线程的合理使用可以将CPU的性能发挥到最大,对于使用线程池有以下优点:
任务应该包括哪些内容?
应该包括:输入数据、解决方法、输出数据
这些必须都传给线程池中的线程才行,线程池中的线程从任务中拿取输入数据调用解决方法,最后把输出结果写入,线程池不需要对任务做任何多余的操作!理解这一点很重要。而这个方法函数叫做——回调函数
结构体中的对象包括
std::vector<pthread_t> pool;
std::queue<Task *> task_queue; //任务队列
pthread_cond_t cond;
pthread_mutex_t mutex;
大体思路是:任务队列不为空就通过条件变量向线程池中的线程发送信号执行任务,如果任务队列为空,则线程池中的线程在cond条件变量下等待。
代码如下:
// pthread_getconcurrency //获取线程的最大并发数
#include
#include
#include
#include
#include
#include
namespace sht
{
class Task // 所有的任务都必须从这个类里面继承
{
public:
virtual void operator()() = 0;
};
class ThreadPool
{
public:
static void *fun(void *args)
{
ThreadPool *p = (ThreadPool *)args;
while (true)
{
pthread_mutex_lock(&(p->mutex));
while (p->task_queue.empty())
{
pthread_cond_wait(&(p->cond), &(p->mutex));
}
Task *mission = p->task_queue.front();
p->task_queue.pop();
pthread_mutex_unlock(&(p->mutex));
// 执行任务
(*mission)();
}
}
ThreadPool()
{
// 获取硬件的最大并发数
int sz = std::thread::hardware_concurrency();
std::cout << sz << std::endl;
pool.resize(sz);
for (int i = 0; i < sz; i++)
pthread_create(&pool[i], nullptr, fun, (void *)this);
pthread_cond_init(&cond, nullptr);
pthread_mutex_init(&mutex, nullptr);
}
void push(Task *p)
{
pthread_mutex_lock(&mutex);
task_queue.push(p);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return;
}
private:
std::vector<pthread_t> pool;
// 这里我们实现一个阻塞队列
std::queue<Task *> task_queue;
pthread_cond_t cond;
pthread_mutex_t mutex;
};
}
注意
void operator ()()
,仅此而已,如果你不想使用纯虚类,也可以把线程池设计成一个模板,把任务当成模板插入线程池不足
结构体中的对象包括
std::vector<pthread_t> pool;
sem_t sem; // 信号量
pthread_mutex_t mutex; // 互斥锁
std::list<task *> task_queue; // 任务队列
bool flag = true; // 终止线程池
大体思路是: 把信号量的大小设置成任务队列task_queue的大小,这样临界资源的粒度就变小了,实现了生产和消费的解耦
#include
#include
#include
#include
#include
// 反应堆式 线程池
// 需要实现单例模式
// 需要用信号量实现
namespace sht
{
class task
{
public:
virtual void operator()() = 0;
};
class ThreadPool
{
public:
static void *fun(void *args)
{
ThreadPool *_this = static_cast<ThreadPool *>(args);
task *mission = nullptr;
while (_this->flag)
{
// std::cout << "p" << (_this->task_queue).size() << std::endl;
sem_wait(&(_this->sem));
// 判断任务队列不能为0
if ((_this->task_queue).size() != 0)
{
pthread_mutex_lock(&(_this->mutex));
if ((_this->task_queue).size() != 0)
{
mission = (_this->task_queue).front();
(_this->task_queue).pop_front();
}
pthread_mutex_unlock(&(_this->mutex));
// 执行任务
(*mission)();
}
}
return nullptr;
}
void push_task(task *t)
{
pthread_mutex_lock(&mutex);
task_queue.push_back(t);
// std::cout << task_queue.size() << std::endl;
sem_post(&sem);
pthread_mutex_unlock(&mutex);
}
static ThreadPool *get_threadpool()
{
if (singleton == nullptr)
{
pthread_mutex_lock(&pool_mutex);
if (singleton == nullptr)
{
singleton = new ThreadPool;
}
pthread_mutex_unlock(&pool_mutex);
}
return singleton;
}
static void destroy_threadpool()
{
if (singleton != nullptr)
{
pthread_mutex_lock(&pool_mutex);
if (singleton != nullptr)
{
singleton->~ThreadPool();
}
pthread_mutex_unlock(&pool_mutex);
}
}
private:
ThreadPool()
{
// std::cout << std::thread::hardware_concurrency() << std::endl;
pool.resize(std::thread::hardware_concurrency());
sem_init(&sem, 0, pool.size());
pthread_mutex_init(&mutex, nullptr);
for (int i = 0; i < pool.size(); i++)
{
pthread_create(&pool[i], nullptr, fun, (void *)this);
}
}
~ThreadPool()
{
flag = true;
pthread_mutex_destroy(&mutex);
sem_destroy(&sem);
}
static ThreadPool *singleton;
static pthread_mutex_t pool_mutex;
std::vector<pthread_t> pool;
sem_t sem; // 信号量
pthread_mutex_t mutex; // 互斥锁
std::list<task *> task_queue; // 任务队列
bool flag = true; // 终止线程池
};
ThreadPool *ThreadPool::singleton = nullptr;
pthread_mutex_t ThreadPool::pool_mutex = PTHREAD_MUTEX_INITIALIZER;
} // namespace sht
最后线程池被设计成了单例模式,可以保证该线程池全局唯一