#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<vector>
#include<queue>
#include<memory>
using namespace std;
class comsumer;
//3个接口,解决相互调用和扩展性的问题
class task_ifc {
public:
virtual void do_work() = 0;
};
class consumer_ifc {
thread th;
task_ifc* m_task;
};
int main_();
class consumerManager_ifc {
protected:
vector<consumer_ifc*> cmer;
queue<std::unique_ptr<task_ifc>> tasks;
condition_variable cond;//控制整个流程的环境
condition_variable cond_task_send_out;//控制任务发送的环境
mutex inner;//mtx是锁消费者的,inner是锁manage的
mutex task_sent_out;//这个是的锁
std::thread th_task_sent_out;
bool is_working = 1;
unsigned int max_consumer;//消费者的数量
unsigned int can_invoke_consumer_size;//当前可调用消费者的个数
friend class consumer;
void cmer_over_task() {
std::lock_guard<std::mutex> lock_g(inner);
can_invoke_consumer_size++;
}
void task_send_out() {//开启子线程,在后台进行任务分配
std::unique_lock<std::mutex> lock_u(task_sent_out);
while (is_working) {
cond_task_send_out.wait(lock_u);
while (tasks.size() > 0) {//探测到有任务
if (can_invoke_consumer_size > 0) {//如果有可调用的consumer的话就将分配任务
cond.notify_all();
}
else {
break;
}
}
}
}
void cmer_start_task() {
std::lock_guard<std::mutex> lock_g(inner);
can_invoke_consumer_size--;
}
friend int main_();
public:
virtual void push(task_ifc* new_task) = 0;
};
class task :public task_ifc {
int a = 0;
public:
task(){}
void set(int x) {
a = x;
}
void do_work() override {
cout << ".";
this_thread::sleep_for(std::chrono::milliseconds(10));
}
};
class consumer:public consumer_ifc {
thread th;
std::unique_ptr<task_ifc> m_task;
bool is_can_invoke = 1;
bool is_working = 0;
consumerManager_ifc* manger;//获取管理者的引用
std::mutex mtx;
void task_delete() {
m_task = nullptr;//将智能指针置空
}
consumer(consumerManager_ifc* manger)
: manger(manger) {
th = thread(&consumer::take, this);
}
consumer(const consumer& cmer) = delete;//删除拷贝构造函数
consumer(consumer&& cmer) {//支持移动构造函数
th = std::move(cmer.th);
m_task = std::move(cmer.m_task);
is_can_invoke = cmer.is_can_invoke;
is_working = cmer.is_working;
manger = cmer.manger;
}
void take() {
unique_lock<std::mutex> lock_u(mtx);
cout << "线程构造完毕" << endl;
while (is_can_invoke) {
manger->cond.wait(lock_u);//等待管理者wake,唤醒后锁会自动lock,保证下面操作的准确性
if (!get_task()) {//获取任务失败
continue;
}
is_working = true;//设置工作状态
manger->cmer_start_task();//将开始工作的信息传递给manger
m_task.get()->do_work();//开始工作
task_delete();//将完成的任务删除
manger->cmer_over_task();//将工作完成的信息传递给manger
is_working = false;//设置工作状态
manger->cond_task_send_out.notify_one();//提醒manger发配任务
}
}
bool get_task() {
manger->inner.lock();
if (manger->tasks.size() == 0) {
manger->inner.unlock();
return false;
}
m_task =std::move(manger->tasks.front());//获取任务
manger->tasks.pop();//删除任务
manger->inner.unlock();
return true;
}
~consumer() {//线程的生命周期是消费者创建开始到消费者析构
if (th.joinable())
th.join();
}
friend class consumerManager;
};
class consumerManager:public consumerManager_ifc {
public:
consumerManager(unsigned int size = 1) {//创建一个多线程执行任务的Manger
cmer.resize(size);
for (int i = 0; i < size; i++) {
cmer[i] = new consumer(this);
}
can_invoke_consumer_size = size;
th_task_sent_out = std::thread(&consumerManager::task_send_out, this);
}
void push(task_ifc* new_task) {
std::unique_lock<std::mutex> lock_g(inner);//用inner锁来保证tasks的访问正确性
std::unique_ptr<task_ifc> unique_new_task(new_task);
tasks.push(std::move(unique_new_task));
if (can_invoke_consumer_size > 0) {//获取外界的一个任务,判断是否有消费者可以调用;
cond.notify_one();
}
}
~consumerManager() {
}
};
class producer {
consumerManager_ifc* manger;
public:
producer(consumerManager_ifc* manger)
:manger(manger) {}
void product_task() {
int x = rand() % 10;
task* new_task = new task();
new_task->set(x);
manger->push(new_task);
}
friend int main_();
};
int main_() {
consumerManager_ifc* manger = new consumerManager(50);
producer pder(manger);
while (1) {
int x; cin >> x;
if (x == -1) {
cout << manger->tasks.size() << endl;
}
for (int i = 0; i < x; i++) {
pder.product_task();
}
cout << endl << "push_over" << endl;
}
}
int main() {
cout << "多线程任务分配器" << endl;
main_();
}