目录
Thread.hpp
LockGuard.hpp
ThreadPool.hpp
Task.hpp
main.cc
基本概念:一种线程的使用模式。线程过多会带来调度开销,进而影响局部性和整体性能。线程池维护着多个线程,等待着监督管理着分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分应用,还能防止过度调用。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量
#pragma once
#include
#include
#include
#include
#include
#include
namespace MyThread
{
typedef std::function func_t;
const int num = 1024;
class Thread
{
public:
Thread()
{
char nameBuffer[num];
snprintf(nameBuffer, sizeof(nameBuffer), "thread-%d", threadNum++);
_name = nameBuffer;
}
void start(func_t func, void* args = nullptr)
{
_func = func;
_args = args;
int n = pthread_create(&_tid, nullptr, start_routine, this);
assert(n == 0);
}
void join()
{
int n = pthread_join(_tid, nullptr);
assert(n == 0);
}
std::string thread_name() {
return _name;
}
void* callback()
{
return _func(_args);
}
private:
static void* start_routine(void* args) {
Thread* _this = static_cast(args);
return _this->callback();
}
private:
std::string _name;
func_t _func;
void* _args;
pthread_t _tid;
static int threadNum;
};
int Thread::threadNum = 1; //线程编号
}
#pragma once
#include
#include
class Mutex
{
public:
Mutex(pthread_mutex_t* plock)
: _plock(plock)
{}
void lock()
{
if (_plock)
{
pthread_mutex_lock(_plock);
}
}
void unlock()
{
if (_plock)
{
pthread_mutex_unlock(_plock);
}
}
private:
pthread_mutex_t* _plock;
};
class LockGuard
{
public:
LockGuard(pthread_mutex_t* mutex): _mutex(mutex)
{
_mutex.lock();
}
~LockGuard()
{
_mutex.unlock();
}
private:
Mutex _mutex;
};
#pragma once
#include "Thread.hpp"
#include "LockGuard.hpp"
#include
#include
#include
#include
using namespace MyThread;
const int g_num = 5;
template
class ThreadPool;
template
class ThreadData
{
public:
ThreadData(ThreadPool* tp, const std::string& n)
: threadpool(tp), name(n)
{}
ThreadPool* threadpool;
std::string name;
};
template
class ThreadPool
{
public:
void lock_queue()
{
pthread_mutex_lock(&_mutex);
}
void unlock_queue()
{
pthread_mutex_unlock(&_mutex);
}
bool is_queue_empty()
{
return _task.empty();
}
void thread_wait()
{
pthread_cond_wait(&_cond, &_mutex);
}
T pop()
{
T t = _task.front();
_task.pop();
return t;
}
pthread_mutex_t* mutex()
{
return &_mutex;
}
public:
void run()
{
for (const auto& t: _threads)
{
ThreadData* td = new ThreadData(this, t->thread_name());
t->start(handler_task, td);
std::cout << t->thread_name() << "start ..." << std::endl;
}
}
void push(const T& in)
{
LockGuard lockGuard(&_mutex);
_task.push(in);
pthread_cond_signal(&_cond);
}
~ThreadPool()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond);
for (const auto& t: _threads)
{
delete t;
}
}
//单例模式
static ThreadPool* get_instance()
{
if (tp == nullptr)
{
_singLock.lock();
tp = new ThreadPool();
_singLock.unlock();
}
return tp;
}
private:
static void* handler_task(void* args)
{
ThreadData* td = (ThreadData*)args;
while (true)
{
T t;
{
LockGuard lockGuard(td->threadpool->mutex());
while (td->threadpool->is_queue_empty())
{
td->threadpool->thread_wait();
}
t = td->threadpool->pop();
}
std::cout << td->name << "获取一个任务:" << t.to_task_string() << " 并处理完成:" << t() << std::endl;
}
delete td;
return nullptr;
}
ThreadPool(const int& num = g_num)
: _num(num)
{
pthread_mutex_init(&_mutex, nullptr);
pthread_cond_init(&_cond, nullptr);
for (int i = 0; i < num; ++i)
{
_threads.push_back(new Thread());
}
}
void operator=(const ThreadPool&) = delete;
ThreadPool(const ThreadPool&) = delete;
private:
int _num;
std::vector _threads;
std::queue _task;
pthread_mutex_t _mutex;
pthread_cond_t _cond;
static ThreadPool* tp;
static std::mutex _singLock;
};
template
ThreadPool* ThreadPool::tp = nullptr;
template
std::mutex ThreadPool::_singLock;
#pragma once
#include
#include
#include
#include
#include
class Task
{
using func_t = std::function;
public:
Task()
{}
Task(int x, int y, char op, func_t func)
: _x(x), _y(y), _op(op), _callback(func)
{}
std::string operator()()
{
int res = _callback(_x, _y, _op);
char buffer[1024];
snprintf(buffer, sizeof(buffer), "%d %c %d = %d", _x, _op, _y, res);
return buffer;
}
std::string to_task_string()
{
char buffer[1024];
snprintf(buffer, sizeof(buffer), "%d %c %d = ?", _x, _op, _y);
return buffer;
}
private:
int _x, _y;
char _op;
func_t _callback;
};
const std::string oper = "+-*/%";
int my_math(int x, int y, char op)
{
if (y == 0 && (op == '/' || op == '%'))
{
std::cerr << "div zero error!" << std::endl;
return -1;
}
switch (op)
{
case '+':
return x + y;
case '-':
return x - y;
case '*':
return x * y;
case '/':
return x / y;
case '%':
return x % y;
default:
std::cerr << "oper error!" << std::endl;
return -1;
}
}
#include "ThreadPool.hpp"
#include "Task.hpp"
#include
#include
#include
int main()
{
srand((unsigned int)time(nullptr) ^ getpid());
ThreadPool::get_instance()->run();
while (1)
{
int x = rand() % 10;
int y = rand() % 5;
char op = oper[rand() % oper.size()];
Task t(x, y, op, my_math);
ThreadPool::get_instance()->push(t);
sleep(1);
}
return 0;
}