使用 condition_variable::wait(unique_lock<mutex>&lck, Predicate pred) 时,必须保证条件变量通过notify唤醒的同时,wait 的第二个参数 Predicate 返回 true 了才可以往下走。必须两个条件同时满足,如果notify的时候Predicate返回时false一样的唤不醒线程。
cpp
#include <iostream>
#include <future>
#include <chrono>
#include <string>
#include<functional>
#include <queue>
using Task = std::function<void()>;
class ThreaPool
{
public:
void start()
{
running_ = true;
}
bool is_running()
{
return running_;
}
void stop()
{
std::cout << "stop..." << std::endl;
running_ = false;
std::unique_lock<std::mutex> lk(qmutext_);
tasks_.push([]() { std::cout << "hello pool end " << std::endl; });
cond_.notify_all();
}
void push_task(Task task)
{
if (!running_)
{
return;
}
std::unique_lock<std::mutex> lk(qmutext_);
tasks_.push(task);
cond_.notify_one();
}
ThreaPool(int count)
{
for (int i = 0; i < count; i++)
{
pool_.emplace_back([this]()
{
while (true)
{
Task task;
{
std::unique_lock<std::mutex> lk(qmutext_);
std::cout << "wait 1" << std::endl;
cond_.wait(lk, [this] {return !running_ || !tasks_.empty(); });
std::cout << "wait 2" << std::endl;
if (!tasks_.empty())
{
task = std::move(tasks_.front());
tasks_.pop();
}
}
if (task)
{
task();
}
if (!this->is_running())
{
std::cout << "stoped 1" << std::endl;
std::unique_lock<std::mutex> lk(qmutext_);
if (tasks_.empty()) {
std::cout << "stoped 2" << std::endl;
return;
}
}
}
});
}
}
~ThreaPool()
{
for (std::thread& worker : pool_) {
worker.join();
}
};
private:
std::vector<std::thread> pool_;
std::mutex qmutext_;
std::condition_variable cond_;
std::queue< Task > tasks_;
std::atomic_bool running_{ true };
};
int main()
{
ThreaPool pool(5);
std::this_thread::sleep_for(std::chrono::seconds(1));
pool.push_task([]() { std::cout << "hello pool 1 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 2 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 3 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 4 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 5 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 6 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 7 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 8 \n" << std::endl; });
pool.push_task([]() { std::cout << "hello pool 9 \n" << std::endl; });
std::this_thread::sleep_for(std::chrono::seconds(1));
pool.stop();
return 0;
}