POSIX的thread默认是joinable,需要手工调用pthread_join函数来回收,也可以调用pthread_detach将其变为detachable,此时不需要手工回收线程。
封装时有三个注意事项:
下面采用继承的方式进行封装,子类只需公有继承Thread类并覆写其run方法。
#ifndef _THREAD_H_
#define _THREAD_H_
#include "noncopyable.h"
#include
#include
#include
#define CHECK(exp)\
if(!exp) \
{ \
fprintf(stderr,"file:%s,line:%d Exp:[" #exp "] not return 0\n",__FILE__,__LINE__);abort();\
}
class Thread: public noncopyable{
public:
Thread();
virtual ~Thread();
void join();
virtual void run() = 0;
void start();
pthread_t getThreadId(){
return tid_;
}
private:
static void* func(void* arg);
private:
pthread_t tid_;
bool isrunning_;
};
#endif // _THREAD_H_
#include "Thread.h"
#include
Thread::Thread():tid_(0),isrunning_(false){
}
void Thread::start(){
CHECK(!pthread_create(&tid_,NULL,Thread::func,(void*)this));
isrunning_ = true;
}
void Thread::join(){
assert(isrunning_ == true);
CHECK(!pthread_join(tid_,NULL));
isrunning_ = false;
}
void* Thread::func(void* arg){
Thread* t = (Thread*)arg;
t->run();
return NULL;
}
Thread::~Thread(){
if(isrunning_){
CHECK(!pthread_detach(tid_));
}
}
还是利用封装Condition时的例子:
https://blog.csdn.net/littleflypig/article/details/89210990
这次把线程换成我们自己的。
#include
#include "MutexLock.h"
#include
#include
#include
#include
#include "Condition.h"
#include "Thread.h"
using namespace std;
const int num = 10;
int count=0;
MutexLock mutex;
Condition cond(mutex);
pid_t gettid(){
return syscall(__NR_gettid);
}
class ConsumerThread : public Thread{
public:
void run(){
pid_t tid = gettid();
for(int i=0;i<num;++i){
MutexLockGuard lock(mutex);
while(count == 0){
cond.wait();
}
cout<<"consume "<<tid<<": "<<count<<endl;
count--;
}
}
};
class ProducerThread : public Thread{
public:
void run(){
pid_t tid = gettid();
for(int i=0;i<2*num;++i){
MutexLockGuard lock(mutex);
count++;
cout<<"produce "<<tid<<": "<<count<<endl;
cond.notify();
}
}
};
int main()
{
ConsumerThread c1,c2;
ProducerThread p;
c1.start();
c2.start();
p.start();
c1.join();
c2.join();
p.join();
cout<<count<<endl;
}
有几个点需要注意:
参考:http://www.cnblogs.com/inevermore/p/4008572.html
利用std的function模板,需要注意的点是setCallback的参数必须要声明为const类型的引用,否则编译会报错。
#ifndef _THREAD2_H_
#define _THREAD2_H_
#include "noncopyable.h"
#include
#include
#include
#include
#define CHECK(exp)\
if(!exp) \
{ \
fprintf(stderr,"file:%s,line:%d Exp:[" #exp "] not return 0\n",__FILE__,__LINE__);abort();\
}
typedef std::function<void ()> funcCallback;
class Thread2: public noncopyable{
public:
Thread2();
~Thread2();
void join();
void start();
pthread_t getThreadId(){
return tid_;
}
void setCallback(const funcCallback& c){
callback_ = c;
}
private:
static void* func(void* arg);
private:
pthread_t tid_;
bool isrunning_;
funcCallback callback_;
};
#endif // _THREAD_H_
#include "Thread2.h"
#include
Thread2::Thread2():tid_(0),isrunning_(false){
}
void Thread2::start(){
CHECK(!pthread_create(&tid_,NULL,Thread2::func,(void*)this));
isrunning_ = true;
}
void Thread2::join(){
assert(isrunning_ == true);
CHECK(!pthread_join(tid_,NULL));
isrunning_ = false;
}
void* Thread2::func(void* arg){
Thread2* t = (Thread2*)arg;
t->callback_();
return NULL;
}
Thread2::~Thread2(){
if(isrunning_){
CHECK(!pthread_detach(tid_));
}
}
使用起来感觉比较方便,不用继承了
include <iostream>
#include "MutexLock.h"
#include
#include
#include
#include
#include "Condition.h"
#include "Thread2.h"
using namespace std;
const int num = 10;
int count=0;
MutexLock mutex;
Condition cond(mutex);
pid_t gettid(){
return syscall(__NR_gettid);
}
void consume(){
pid_t tid = gettid();
for(int i=0;i<num;++i){
MutexLockGuard lock(mutex);
while(count == 0){
cond.wait();
}
cout<<"consume "<<tid<<": "<<count<<endl;
count--;
}
}
void produce(){
pid_t tid = gettid();
for(int i=0;i<2*num;++i){
MutexLockGuard lock(mutex);
count++;
cout<<"produce "<<tid<<": "<<count<<endl;
cond.notify();
}
}
int main()
{
Thread2 c1,c2,p;
c1.setCallback(consume);
c2.setCallback(consume);
p.setCallback(produce);
c1.start();
c2.start();
p.start();
c1.join();
c2.join();
p.join();
cout<<count<<endl;
}
而且想要传参数给线程任务函数也是可以的,用bind将参数绑定即可,如下:
void consume(int arg){
pid_t tid = gettid();
for(int i=0;i<num;++i){
MutexLockGuard lock(mutex);
while(count == 0){
cond.wait();
}
cout<<"consume "<<tid<<": "<<count<<endl;
count--;
}
}
int main()
{
Thread2 c1,c2,p;
c1.setCallback(bind(consume,1)); //bind参数
c2.setCallback(bind(consume,2));
p.setCallback(produce);
c1.start();
c2.start();
p.start();
c1.join();
c2.join();
p.join();
cout<<count<<endl;
}