main.cpp
#include<iostream>
#include<chrono>
#include"threadpool.h"
class MyTask : public Task
{
public:
MyTask(int begin, int end)
: begin_(begin)
, end_(end)
{}
Any run()
{
std::cout << "tid:" << std::this_thread::get_id()
<< "begin!" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
int sum = 0;
for (int i = begin_; i <= end_; i++)
sum += i;
std::cout << "tid:" << std::this_thread::get_id()
<< "end!" << std::endl;
return sum;
}
private:
int begin_;
int end_;
};
int main(void)
{
{
ThreadPool pool;
pool.setMode(PoolMode::MODE_CACHED);
pool.start(2);
Result res1 = pool.submitTask(std::make_shared<MyTask>(1, 1000));
Result res2 = pool.submitTask(std::make_shared<MyTask>(1001, 2000));
Result res3 = pool.submitTask(std::make_shared<MyTask>(1, 1000));
Result res4 = pool.submitTask(std::make_shared<MyTask>(1001, 2000));
Result res5 = pool.submitTask(std::make_shared<MyTask>(1, 1000));
Result res6 = pool.submitTask(std::make_shared<MyTask>(1001, 2000));
Result res7 = pool.submitTask(std::make_shared<MyTask>(1001, 2000));
Result res8 = pool.submitTask(std::make_shared<MyTask>(1001, 2000));
int sum1 = res1.getRes().cast_<int>();
int sum2 = res2.getRes().cast_<int>();
int sum3 = res3.getRes().cast_<int>();
int sum4 = res4.getRes().cast_<int>();
int sum5 = res5.getRes().cast_<int>();
int sum6 = res6.getRes().cast_<int>();
int sum7 = res7.getRes().cast_<int>();
int sum8 = res8.getRes().cast_<int>();
std::cout << "结果为结果为" << sum1 << std::endl;
std::cout << "结果为结果为" << sum2 << std::endl;
std::cout << "结果为结果为" << sum3 << std::endl;
std::cout << "结果为结果为" << sum4 << std::endl;
std::cout << "结果为结果为" << sum5 << std::endl;
std::cout << "结果为结果为" << sum6 << std::endl;
std::cout << "结果为结果为" << sum7 << std::endl;
std::cout << "结果为结果为" << sum8 << std::endl;
std::cout << "main over!" << std::endl;
getchar();
}
std::cout << "main over over over!" << std::endl;
return 0;
}
threadpool.cpp
#include"threadpool.h"
#include<functional>
const int TASK_MAX_THREADHOLD = 1024;
const int WAIT_TIME = 50;
ThreadPool::ThreadPool():m_initThreadSize(0),m_taskSize(0)
,m_maxTaskSize(TASK_MAX_THREADHOLD)
,m_poolMode(PoolMode::MODE_FIXED)
,m_idleThread(0)
,m_curRunningThread(0)
,m_threadSize(0)
,m_maxThread(300)
,m_isRunning(false)
{}
ThreadPool::~ThreadPool()
{
std::cout << "线程池析构" << std::endl;
m_isRunning = false;
std::unique_lock<std::mutex> lock(m_taskQueMtx);
std::cout << "获得锁成功" << std::endl;
m_notEmpty.notify_all();
m_exit_Cond.wait(lock, [&]()->bool {return m_threads.size() == 0; });
std::cout << "线程池析构成功" << std::endl;
}
void ThreadPool::setMaxThread(int maxThread)
{
m_maxThread = maxThread;
}
void ThreadPool::setMode(PoolMode mode)
{
m_poolMode = mode;
}
void ThreadPool::setMaxTaskSize(int maxTaskSize)
{
m_maxTaskSize = maxTaskSize;
}
Result ThreadPool::submitTask(std::shared_ptr<Task> sp)
{
std::unique_lock<std::mutex> lock(m_taskQueMtx);
if (!m_notFull.wait_for(lock, std::chrono::seconds(1), [&]()->bool {return m_taskQue.size() < (size_t)m_maxTaskSize; }))
{
std::cerr << "任务未进入线程" << std::endl;
return Result(sp, false);
}
m_taskQue.emplace(sp);
m_taskSize++;
m_notEmpty.notify_all();
if (m_poolMode == PoolMode::MODE_CACHED
&& m_taskSize > m_initThreadSize
&& m_threadSize < m_maxTaskSize)
{
std::cout << ">>> create new thread..." << std::endl;
auto ptr = std::make_unique<Thread>(std::bind(&ThreadPool::threadFunc, this,std::placeholders::_1));
int threadID = ptr->getID();
m_threads.emplace(threadID,std::move(ptr));
m_threads[threadID]->start();
m_threadSize++;
m_idleThread++;
}
return Result(sp);
}
void ThreadPool::start(int initTaskSize)
{
m_isRunning = true;
m_initThreadSize = initTaskSize;
m_threadSize = initTaskSize;
for (int i = 0; i < initTaskSize; i++)
{
auto ptr = std::make_unique<Thread>(std::bind(&ThreadPool::threadFunc, this,std::placeholders::_1));
int threadID = ptr->getID();
m_threads.emplace(threadID,std::move(ptr));
}
for (int i = 0; i < initTaskSize; i++)
{
m_threads[i]->start();
m_idleThread++;
}
}
void ThreadPool::threadFunc(int threadID)
{
auto lastTime = std::chrono::high_resolution_clock().now();
for (;;)
{
std::shared_ptr<Task> task;
{
std::unique_lock<std::mutex> lock(m_taskQueMtx);
while (m_taskQue.size() == 0)
{
if (!m_isRunning)
{
m_threads.erase(threadID);
std::cout << "threadid:" << std::this_thread::get_id() << " exit!"
<< std::endl;
m_exit_Cond.notify_all();
return;
}
if (m_poolMode == PoolMode::MODE_CACHED)
{
if(std::cv_status::timeout ==
m_notEmpty.wait_for(lock, std::chrono::seconds(1)))
{
auto now = std::chrono::high_resolution_clock().now();
auto dur = std::chrono::duration_cast<std::chrono::seconds>(now - lastTime);
if (dur.count() > WAIT_TIME && m_threadSize > m_initThreadSize)
{
m_threads.erase(threadID);
m_threadSize--;
m_idleThread--;
std::cout << "threadId: " << std::this_thread::get_id() << " exit"
<< std::endl;
return;
}
}
}
else
{
m_notEmpty.wait(lock);
}
}
m_idleThread--;
task = m_taskQue.front();
m_taskQue.pop();
m_taskSize--;
if (m_taskQue.size() > 0)
{
m_notEmpty.notify_all();
}
m_notFull.notify_all();
}
if (task != nullptr)
{
task->exec();
}
m_idleThread++;
lastTime = std::chrono::high_resolution_clock().now();
}
}
int Thread::m_generateID = 0;
int Thread::getID()const
{
return m_threadID;
}
void Thread::start()
{
std::thread t(m_func,m_threadID);
t.detach();
}
Thread::Thread(ThreadFunc func) :m_func(func), m_threadID(m_generateID++)
{
}
Thread::~Thread()
{
}
Result::Result(std::shared_ptr<Task> task, bool isVaild) :m_isVaild(isVaild), m_task(task)
{
m_task->setResult(this);
}
Any Result::getRes()
{
if (!m_isVaild)
{
return "";
}
m_semaphore.wait();
return std::move(m_any);
}
void Result::setRes(Any any)
{
this->m_any = std::move(any);
m_semaphore.post();
}
Task::Task():m_res(nullptr){}
void Task::exec()
{
if (m_res != nullptr)
{
m_res->setRes(run());
}
}
void Task::setResult(Result* res)
{
m_res = res;
}
threadpool.h
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include<iostream>
#include<vector>
#include<queue>
#include<memory>
#include<mutex>
#include<atomic>
#include<condition_variable>
#include<thread>
#include<functional>
#include<unordered_map>
class Any;
class Result;
class Task
{
public:
Task();
~Task() = default;
void exec();
virtual Any run() = 0;
void setResult(Result* res);
private:
Result* m_res;
};
class Thread
{
public:
using ThreadFunc = std::function<void(int)>;
Thread(ThreadFunc func);
~Thread();
void start();
int getID()const;
private:
ThreadFunc m_func;
static int m_generateID;
int m_threadID;
};
class Any
{
public:
Any() = default;
~Any() = default;
Any(const Any&) = delete;
Any& operator=(const Any&) = delete;
Any(Any&&) = default;
Any& operator=(Any&&) = default;
template<typename T>
Any(T data) :m_base(std::make_unique<Derive<T>>(data))
{
}
template<typename T>
T cast_()
{
Derive<T>* pd = dynamic_cast<Derive<T>*>(m_base.get());
if (pd == nullptr)
{
throw "type is unmatch!";
}
return pd->m_data;
}
private:
class Base
{
public:
virtual ~Base() = default;
};
template<typename T>
class Derive : public Base
{
public:
Derive(T data) :m_data(data) {}
T m_data;
};
private:
std::unique_ptr<Base> m_base;
};
class Semaphore
{
public:
Semaphore(int limit = 0) :m_resLimit(limit) {}
~Semaphore() = default;
void wait()
{
std::unique_lock<std::mutex> lock(m_mtx);
m_condition.wait(lock, [&]()->bool {return m_resLimit > 0; });
m_resLimit--;
}
void post()
{
std::unique_lock<std::mutex> lock(m_mtx);
m_resLimit++;
m_condition.notify_all();
}
private:
int m_resLimit;
std::mutex m_mtx;
std::condition_variable m_condition;
};
class Result
{
public:
Result(std::shared_ptr<Task>, bool isVaild = true);
~Result() = default;
Any getRes();
void setRes(Any any);
private:
Any m_any;
Semaphore m_semaphore;
std::shared_ptr<Task> m_task;
std::atomic_bool m_isVaild;
};
enum class PoolMode
{
MODE_FIXED,
MODE_CACHED,
};
class ThreadPool
{
public:
ThreadPool();
~ThreadPool();
void setMode(PoolMode mode);
void setMaxTaskSize(int maxTaskSize);
Result submitTask(std::shared_ptr<Task> sp);
void start(int initTaskSize = 0);
ThreadPool(const ThreadPool&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
void setMaxThread(int maxThread);
private:
void threadFunc(int threadID);
std::atomic_int m_idleThread;
int m_curRunningThread;
int m_maxThread;
std::atomic_int m_threadSize;
private:
std::unordered_map<int,std::unique_ptr<Thread>> m_threads;
int m_initThreadSize;
std::queue<std::shared_ptr<Task>> m_taskQue;
int m_taskSize;
int m_maxTaskSize;
PoolMode m_poolMode;
std::atomic_bool m_isRunning;
std::condition_variable m_exit_Cond;
std::condition_variable m_notFull;
std::condition_variable m_notEmpty;
std::mutex m_taskQueMtx;
};
#endif