封装一个锁
1.封装一个Mutex
cpp
class Mutex{
public:
Mutex(pthread_mutex_t * lock):_lock(lock)
{}
void Lock()
{
pthread_mutex_lock(_lock);
}
void unLock()
{
pthread_mutex_unlock(_lock);
}
~Mutex()
{}
private:
pthread_mutex_t *_lock;
};
2.封装一个LockGuard
cpp
class LockGuard{
public:
LockGuard(pthread_mutex_t * lock):_mutex(lock)
{
_mutex.Lock();
}
~LockGuard()
{
_mutex.unLock();
}
private:
Mutex _mutex;
};
在底层就可以直接创建一个LockGuard对象,就可以直接对临时资源进行加锁
类似:
cpp
{
LockGuard(&mutex);
//临界资源
}
创建线程池
封装线程
1.成员变量
cpp
private:
std::string _threadname;
pthread_t _pid;
func_t<T> _func;
bool _isrunning;
T _data;
cpp
template <class T>
using func_t = std::function<void(T&)>;
我们创建一个fun_t 用来传递一个函数给线程,在内部用来回调。
2.构造函数
cpp
Thread(std::string threadname, func_t<T> func, T& data)
: _threadname(threadname), _pid(0), _func(func), _isrunning(false), _data(data)
{
}
3.Start函数和Join函数
cpp
bool Start()
{
int n = pthread_create(&_pid, nullptr, ThreadRoutine, this);
if (n == 0)
{
_isrunning = true;
return true;
}
return false;
}
bool Join()
{
if(!_isrunning) return true;
int n=pthread_join(_pid,nullptr);
if(n==0)
{
_isrunning=false;
return true;
}
else
{
return false;
}
}
4.在创建线程传递一个ThreadRoution函数
cpp
static void *ThreadRoutine(void *args) // 类内方法,
{
// (void)args; // 仅仅是为了防止编译器有告警
Thread *ts = static_cast<Thread *>(args);
ts->_func(ts->_data);
return nullptr;
}
ThreadRountion可不可以为类内函数?
不可以,类内函数默认隐藏的传递this指针,我们必须设置为静态函数函数,再传递this指针。
cpp
#pragma once
#include <iostream>
#include <pthread.h>
#include <functional>
#include <cstring>
template <class T>
using func_t = std::function<void(T&)>;
template <class T>
class Thread
{
public:
Thread(std::string threadname, func_t<T> func, T& data)
: _threadname(threadname), _pid(0), _func(func), _isrunning(false), _data(data)
{
}
static void *ThreadRoutine(void *args) // 类内方法,
{
// (void)args; // 仅仅是为了防止编译器有告警
Thread *ts = static_cast<Thread *>(args);
ts->_func(ts->_data);
return nullptr;
}
bool Start()
{
int n = pthread_create(&_pid, nullptr, ThreadRoutine, this);
if (n == 0)
{
_isrunning = true;
return true;
}
return false;
}
bool Join()
{
if(!_isrunning) return true;
int n=pthread_join(_pid,nullptr);
if(n==0)
{
_isrunning=false;
return true;
}
else
{
return false;
}
}
const std::string& Threadname()
{
return _threadname;
}
private:
std::string _threadname;
pthread_t _pid;
func_t<T> _func;
bool _isrunning;
T _data;
};
创建线程池
我们打算用queue来储存任务,用vector数组储存线程
当任务队列为空时,我们用条件变量去控制线程睡眠,队列Push进任务再控制线程醒来。
1.成员变量
cpp
private:
queue<T> _taskq;
vector<Thread<ThreadData>> _ptdv;
pthread_mutex_t _mutex;
pthread_cond_t _cond;
int _thread_num;
2.构造函数
初始化锁,条件变量,并创建线程。
cpp
pthread_pool(int thread_num = defaultthreadnum) : _thread_num(thread_num)
{
pthread_mutex_init(&_mutex, nullptr);
pthread_cond_init(&_cond, nullptr);
for (int i = 1; i <= defaultthreadnum; i++)
{
string threadname("thread-");
threadname += to_string(i);
ThreadData td(threadname);
Thread<ThreadData> t(threadname,
std::bind(&pthread_pool<T>::pthread_Run, this, std::placeholders::_1), td);
_ptdv.push_back(t);
lg.LogMessage(Info, "%s is created...\n", threadname.c_str());
}
}
任务队列为空,让所有线程休眠,队列中有任务,直接让线程执行任务:t()
cpp
void pthread_Run(ThreadData &data)
{
while (true)
{
T t;
{
LockGuard ld(&_mutex);
if (_taskq.empty())
{
allthreadsleep(data);
}
t = _taskq.front();
_taskq.pop();
}
t();
{
LockGuard ld(&_mutex);
lg.LogMessage(Info, "Thread name:%s is handling: %s \n", data._name.c_str(), t.PrintTask().c_str());
lg.LogMessage(Info, "Thread name:%s get result: %s \n", data._name.c_str(), t.PrintResult().c_str());
}
}
}
3.进程唤醒与进程休眠
cpp
void allthreadwakeup()
{
pthread_cond_signal(&_cond);
}
void allthreadsleep(const ThreadData &data)
{
lg.LogMessage(Debug, "no task, %s is sleeping...\n", data._name.c_str());
pthread_cond_wait(&_cond, &_mutex);
}
4.Push()
cpp
void Push(T &task)
{
{
LockGuard ld(&_mutex);
_taskq.push(task);
// 插入任务后唤醒进程
allthreadwakeup();
}
}
cpp
#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include <cstring>
#include <functional>
#include <unistd.h>
#include "pthread.hpp"
#include "LockGuard.hpp"
#include "Log.hpp"
using namespace std;
static const int defaultthreadnum = 5;
template <class T>
using func_r = std::function<void(T)>;
class ThreadData
{
public:
ThreadData(string name) : _name(name)
{
}
~ThreadData()
{
}
public:
string _name;
};
template <class T>
class pthread_pool
{
public:
static pthread_pool<T> *Getinstance()
{
if (instance == nullptr)
{
pthread_mutex_lock(&_sig_ins);
if (instance == nullptr)
{
instance = new pthread_pool<T>(defaultthreadnum);
lg.LogMessage(Info, "instance is create succeess...\n");
return instance;
}
}
}
pthread_pool(int thread_num = defaultthreadnum) : _thread_num(thread_num)
{
pthread_mutex_init(&_mutex, nullptr);
pthread_cond_init(&_cond, nullptr);
for (int i = 1; i <= defaultthreadnum; i++)
{
string threadname("thread-");
threadname += to_string(i);
ThreadData td(threadname);
Thread<ThreadData> t(threadname,
std::bind(&pthread_pool<T>::pthread_Run, this, std::placeholders::_1), td);
_ptdv.push_back(t);
lg.LogMessage(Info, "%s is created...\n", threadname.c_str());
}
}
pthread_pool(const pthread_pool<T> &pp) = delete;
const pthread_pool<T> &operator=(const pthread_pool<T> &pp) = delete;
void allthreadwakeup()
{
pthread_cond_signal(&_cond);
}
void allthreadsleep(const ThreadData &data)
{
lg.LogMessage(Debug, "no task, %s is sleeping...\n", data._name.c_str());
pthread_cond_wait(&_cond, &_mutex);
}
void pthread_Run(ThreadData &data)
{
while (true)
{
T t;
{
LockGuard ld(&_mutex);
if (_taskq.empty())
{
allthreadsleep(data);
}
t = _taskq.front();
_taskq.pop();
}
t();
{
LockGuard ld(&_mutex);
lg.LogMessage(Info, "Thread name:%s is handling: %s \n", data._name.c_str(), t.PrintTask().c_str());
lg.LogMessage(Info, "Thread name:%s get result: %s \n", data._name.c_str(), t.PrintResult().c_str());
}
}
}
void Start()
{
for (auto &th : _ptdv)
{
th.Start();
lg.LogMessage(Info, "%s is running ...\n", th.Threadname().c_str());
}
}
void Push(T &task)
{
{
LockGuard ld(&_mutex);
_taskq.push(task);
// 插入任务后唤醒进程
allthreadwakeup();
}
}
// Just for debug success!
void Wait()
{
for (auto &th : _ptdv)
{
th.Join();
}
}
~pthread_pool()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond);
}
private:
queue<T> _taskq;
vector<Thread<ThreadData>> _ptdv;
pthread_mutex_t _mutex;
pthread_cond_t _cond;
int _thread_num;
static pthread_pool *instance;
static pthread_mutex_t _sig_ins;
};
template <class T>
pthread_pool<T> *pthread_pool<T>::instance = nullptr;
template <class T>
pthread_mutex_t pthread_pool<T>::_sig_ins = PTHREAD_MUTEX_INITIALIZER;
线程池单利化问题
cpp
static pthread_pool<T> *Getinstance()
{
if (instance == nullptr)
{
pthread_mutex_lock(&_sig_ins);
if (instance == nullptr)
{
instance = new pthread_pool<T>(defaultthreadnum);
lg.LogMessage(Info, "instance is create succeess...\n");
return instance;
}
}
}
在获取单例的函数中,我们是需要加锁的,防止多个线程同时进入创建出多个单利。