场景:
1. 请求线程负责接收运算,然后放入任务队列
2. 计算线程从任务队列中取出线程,计算后输出结果,保存计算结果
3. 多对多模型,多个请求线程和多个计算线程
线程池中两个互斥量,一个是请求队列的,一个是计算队列的。一个条件变量,当有任务时候,用于唤醒计算线程。
两元运算需要手动输入,然后由线程池接收计算。
代码:
TPool.h
#ifndef TPOOL_H
#define TPOOL_H
#include "pthread.h"
#include<queue>
#include<vector>
#include<iostream>
#include<functional>
using namespace std;
class job
{
public:
job();
~job();
int a;
int b;
char c;
double ans;
};
class TPool
{
public:
TPool(int qNum = 5, int cNum = 5); // 请求线程与计算线程的数量
TPool(const TPool &) = default;
TPool &operator=(const TPool &) = delete;
~TPool();
void stop();
private:
bool isRunning; // 线程池的状态
pthread_mutex_t mutex_;//请求队列互斥量
pthread_mutex_t mutex1_;//计算 队列互斥量
pthread_cond_t condition_;//条件变量
pthread_t* threads_rq;//请求 线程数组
pthread_t* threads_c;//计算 线程数组
// vector<int> job;//任务队列
queue<job> jobs;//任务队列
queue<job> answers;//任务队列
// queue<taskType> taskQueue_;//任务队列
void createThreads();//创建线程
int qNum_;
int cNum_;
static void* rqFunc(void* args); // 为什么是static 类成员函数作为回调 需要静态函数
void rqPush(pthread_t tid ); // 请求 入
static void* cFunc(void* args);
void ctake(pthread_t tid ); // 计算 取
};
#endif // !TPOOL_H
TPool.cpp
#include "TPool.h"
#include <pthread.h>
job::job()
{
}
job::~job()
{
}
TPool::TPool(int qNum, int cNum)
{
qNum_ = qNum;
cNum_ = cNum;
isRunning = true;
pthread_mutex_init(&mutex_,NULL);
pthread_mutex_init(&mutex1_, NULL);
pthread_cond_init(&condition_, NULL);
createThreads();
}
TPool::~TPool()
{
stop();
}
void TPool::createThreads()
{
threads_rq = new pthread_t[qNum_];
threads_c = new pthread_t[cNum_];
for(int i = 0; i < qNum_; i++){
cout << "创建第" << i + 1 << "个请求线程" << endl;
pthread_create(&threads_rq[i], NULL, rqFunc, this);
}
for(int i = 0; i < cNum_; i++){
cout << "创建第" << i + 1 << "个计算线程" << endl;
pthread_create(&threads_c[i], NULL, cFunc, this);
}
}
void * TPool::rqFunc(void* args){
pthread_t tid = pthread_self();
TPool* tp = static_cast<TPool*>(args);
while (tp->isRunning)
{
tp->rqPush(tid);
}
}
void TPool::rqPush(pthread_t tid ){
pthread_mutex_lock(&mutex_);
job *j = new job();
cout << "请求线程"<< tid << "准备接受" << endl;
cin >> j->a >> j -> c >> j -> b;
jobs.push(*j);
pthread_mutex_unlock(&mutex_);
pthread_cond_signal(&condition_);
}
void* TPool::cFunc(void* args){
pthread_t tid = pthread_self();
TPool* tp = static_cast<TPool*>(args); // 空类型指针转换为 Threadpool 指针
while (tp->isRunning)
{
tp->ctake(tid);
}
}
void TPool::ctake(pthread_t tid ){
pthread_mutex_lock(&mutex1_);
while (jobs.empty()&&isRunning){ // 防止虚假唤醒
pthread_cond_wait(&condition_, &mutex1_);
}
cout << "计算线程"<< tid<< "取任务" << endl;
job j = jobs.front();
jobs.pop();
pthread_mutex_unlock(&mutex1_);
switch (j.c)
{
case '+':
j.ans = j.a + j.b;
answers.push(j);
cout << j.a << j.c << j.b << "=" <<j.ans << endl;
break;
case '-':
j.ans = j.a - j.b;
answers.push(j);
cout << j.a << j.c << j.b << "=" <<j.ans << endl;
break;
case '*':
j.ans = j.a * j.b;
answers.push(j);
cout << j.a << j.c << j.b << "=" <<j.ans << endl;
break;
case '/':
j.ans = j.a / j.b;
answers.push(j);
cout << j.a << j.c << j.b << "=" <<j.ans << endl;
break;
default:
cout << j.c << "不是有效运算"<< endl;
break;
}
}
void TPool::stop(){
//防止重复stop
if (!isRunning) {
return;
}
cout << "stop the threadpool!!" << endl;
isRunning = false;
//唤醒所有在等待的线程
pthread_cond_broadcast(&condition_);
for (int i = 0; i < qNum_; i++)
{
pthread_join(threads_rq[i], NULL);//join所有线程
}
for (int i = 0; i < cNum_; i++)
{
pthread_join(threads_c[i], NULL);
}
delete[] threads_rq;
delete[] threads_c;
threads_rq = NULL;
threads_c = NULL;
// for(int i = 0; i < jobs.size(); i++){
// free(jobs[i]);
// }
while(!answers.empty()){
job *j = &answers.front();
answers.pop();
delete j;
}
pthread_mutex_destroy(&mutex_);
pthread_mutex_destroy(&mutex1_);
pthread_cond_destroy(&condition_);
}
test.cpp
#include "TPool.h"
#include <unistd.h>
using namespace std;
int main(int argc, const char** argv) {
TPool pool(5,3);
sleep(1200);
// pthread_exit(NULL);
return 0;
}
运行结果: