threadpool.h
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <iostream>
#include <memory>
#include <functional>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <atomic>
class Any
{
public:
Any() = default;
~Any() = default;
Any(const Any&) = delete;
/*Any(const Any&&) = default;*/
Any& operator= (const Any&) = delete;
/*Any& operator= (const Any&&) = default;*/
template <typename T>
T cast_()
{
Derive<T>* pd = dynamic_cast<Derive<T>*>(Base_.get());
if (pd == nullptr)
{
throw "type is not match";
}
return pd->data_;
}
template <typename T>
Any(T data) :Base_(std::make_unique<Derive<T>>(data))
{
}
class Base
{
public:
virtual ~Base() = default;
};
template <typename T>
class Derive :public Base
{
public:
Derive(T data) :data_(data)
{
}
T data_;
};
std::unique_ptr<Base> Base_;
};
class Semaphore
{
public:
Semaphore(int limit = 0) :resLimit_(limit)
{
}
~Semaphore() = default;
void wait()
{
std::unique_lock<std::mutex> locker(mtx_);
cond_.wait(locker, [&]() ->bool
{return resLimit_ > 0; });
resLimit_--;
}
void post()
{
std::unique_lock<std::mutex> locker(mtx_);
resLimit_++;
cond_.notify_all();
}
private:
std::mutex mtx_;
std::condition_variable cond_;
int resLimit_;
};
class Task
{
public:
virtual void run() = 0;
virtual ~Task() = default;
private:
};
class Thread
{
public:
using Func = std::function<void()>;
public:
Thread(Func func);
void start();
~Thread() = default;
private:
Func func_;
};
class ThreadPool
{
public:
ThreadPool();
void start(int initThreadSize = 5);
void threadFunc();
void submitTask(std::shared_ptr<Task> sp);
private:
int initThreadSize_;
int taskMaxSize_;
std::vector<std::unique_ptr<Thread>> threads_;
std::mutex taskQueMtx_;
std::atomic_int taskQueSize_;
std::queue<std::shared_ptr<Task>> taskQue_;
std::condition_variable isNotFull_;
std::condition_variable isNotEmpty_;
};
#endif
threadpool.cpp
#include "threadPool.h"
const static int taskMaxSize = 1024;
/**
* @brief Construct a new Thread:: Thread object
*
* @param func 线程函数
*/
Thread::Thread(Func func)
: func_(func)
{
}
/**
* @brief 线程绑定线程函数 并设置分离属性
*
*/
void Thread::start()
{
std::thread t(func_);
t.detach();
}
ThreadPool::ThreadPool()
: taskMaxSize_(taskMaxSize), taskQueSize_(0)
{
}
/**
* @brief 开启线程池
*
* @param initThreadSize 线程池个数
*/
void ThreadPool::start(int initThreadSize)
{
this->initThreadSize_ = initThreadSize;
for (size_t i = 0; i < initThreadSize_; ++i)
{
std::unique_ptr<Thread> up = std::make_unique<Thread>(std::bind(&ThreadPool::threadFunc, this));
this->threads_.emplace_back(std::move(up));
}
for (const auto& elem : threads_)
{
elem->start();
}
}
/**
* @brief 线程函数
*
*/
void ThreadPool::threadFunc()
{
for (;;)
{
std::unique_lock<std::mutex> locker(taskQueMtx_);
// while(taskQueSize_ == 0)
// {
// isNotEmpty_.wait(locker);
// }
isNotEmpty_.wait(locker, [&]() -> bool
{ return taskQueSize_ > 0; });
auto pTask = taskQue_.front();
taskQue_.pop();
--taskQueSize_;
if (taskQueSize_ > 0)
{
isNotEmpty_.notify_all();
}
isNotFull_.notify_all();
locker.unlock();
if (pTask != nullptr)
{
pTask->run();
}
}
}
/**
* @brief 提交线程任务
*
* @param sp 线程函数
*/
void ThreadPool::submitTask(std::shared_ptr<Task> sp)
{
std::unique_lock<std::mutex> locker(taskQueMtx_);
std::cout << "submitTask" << std::endl;
// while(taskQueSize_ >= taskMaxSize_)
// {
// isNotFull_.wait(locker);
// }
// isNotFull_.wait(locker, [&]() -> bool
// { return taskQueSize_ < taskMaxSize_; });
if (!isNotFull_.wait_for(locker, std::chrono::seconds(1), [&]() -> bool
{return taskQueSize_ < taskMaxSize; }))
{
std::cerr << "task is full submit faile" << std::endl;
return;
}
taskQue_.emplace(sp);
++taskQueSize_;
isNotEmpty_.notify_all();
}
class Mytask : public Task
{
public:
virtual void run() override
{
std::cout << "begin id: " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "end id: " << std::this_thread::get_id() << std::endl;
}
};
int main()
{
ThreadPool threadpool;
threadpool.start();
threadpool.submitTask(std::make_unique<Mytask>());
threadpool.submitTask(std::make_unique<Mytask>());
threadpool.submitTask(std::make_unique<Mytask>());
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}