封装线程类实现生产者消费者——面向对象

面向对象版本:使用纯虚函数+继承实现动态多态

有点缺陷:没有设置线程类对象、互斥锁对象、条件变量对象为不可复制

Condition.hpp

#ifndef __CONDITION__H__
#define __CONDITION__H__

#include <pthread.h>

namespace my
{
class MutexLock;//前向声明

class Condition {
public:
    ~Condition();
    Condition(MutexLock & mutex);
    void wait();
    void notify();//唤醒一个线程
    void notifyall();//唤醒全部线程
    pthread_cond_t * getCondPtr();

private:
    MutexLock & _mutex;
    pthread_cond_t _cond;
};

}

#endif

Condition.cc

#include "Condition.hpp"
#include "MutexLock.hh"
#include <iostream>

namespace my
{
Condition::~Condition()
{
    if(pthread_cond_destroy(getCondPtr()) != 0)
    {
        perror("pthread_cond_destroy");

    }

}
Condition::Condition(MutexLock & mutex)
    :_mutex(mutex)
{
    if(pthread_cond_init(getCondPtr() , nullptr) != 0)
    {
        perror("pthread_cond_init");

    }

}
void Condition::wait()
{
    if(pthread_cond_wait(getCondPtr() , _mutex.getMutexPtr()) != 0)
    {
        perror("pthread_cond_wait");

    }

}
void Condition::notify()//唤醒一个线程
{
    if(pthread_cond_signal(getCondPtr()) != 0)
    {
        perror("pthread_cond_signal");

    }

}
void Condition::notifyall()//唤醒全部线程
{
    if(pthread_cond_broadcast(getCondPtr()) != 0)
    {
        perror("pthread_cond_broadcast");

    }

}
pthread_cond_t * Condition::getCondPtr()
{
    return &_cond;

}

}

 MutexLock.hh

#ifndef __MUTEXTLOCK__H__
#define __MUTEXTLOCK__H__ 

#include <pthread.h>

namespace my
{
class MutexLock {
public:
    ~MutexLock();
    MutexLock();
    pthread_mutex_t * getMutexPtr();
    void lock();
    void unlock();
private:
    pthread_mutex_t _mutex;//互斥锁
};
}//end of nanmespace my

#endif

 MutexLock.cc

#include "MutexLock.hh"
#include <iostream>

namespace my
{

MutexLock::MutexLock()
{
    if(pthread_mutex_init(getMutexPtr(), nullptr) != 0)
    {
        perror("pthread_mutex_init");

    }

}

MutexLock::~MutexLock()
{
    if(pthread_mutex_destroy(getMutexPtr()) != 0)
    {
        perror("pthread_mutex_destroy");

    }

}

void MutexLock::lock()
{
    if(pthread_mutex_lock(getMutexPtr()) != 0)
    {
        perror("pthread_mutex_lock");

    }

}

void MutexLock::unlock()
{
    if(pthread_mutex_unlock(getMutexPtr()) != 0)
    {
        perror("pthread_mutex_unlock");

    }

}

pthread_mutex_t * MutexLock::getMutexPtr()
{
    return &_mutex;

}

}

 thread.hh

#ifndef __THREAD_H__
#define __THREAD_H__

#include <pthread.h>

namespace my
{

class Thread {
public:
    void start();//创建线程
    void join();//等待线程退出
    virtual ~Thread();//设为虚函数:防止派生类资源清理不干净
    Thread();
private:
    static void * threadFun(void* p);//线程执行函数
    virtual void run()=0;  //线程需要实现的任务
    pthread_t _pThid;//线程ID
    bool _isRunning;//标识线程是否在运行
};

}

 thread.cc

#include "thread.hh"
#include <iostream>

namespace my
{

void Thread::start()//创建线程
{
    if(pthread_create(&_pThid, NULL, Thread::threadFun, this) != 0)
    {
        perror("pthread_create");
        return;
    }
    _isRunning = true;//子线程已经运行
}

void Thread::join()
{
    if(_isRunning == true)//子线程运行时才需要pthread_join()
    {
        pthread_join(_pThid, nullptr);
        _isRunning = false;
    }
}

Thread::Thread()
    :_pThid(0)
     ,_isRunning(false)
{}

Thread::~Thread()
{
    if(_isRunning)
    {
        pthread_detach(_pThid);//子线程退出时,资源由OS进行回收
    }
}

void * Thread::threadFun(void* p)
{
    Thread *pTh = (Thread *)p;
    if(pTh != nullptr)
    {
        pTh -> run();//调用派生类重写过的虚函数
    }
    return NULL;
}

}

test.cc

#include "thread.hh"
#include "MutexLock.hh"
#include "Condition.hpp"
#include <unistd.h>
#include <iostream>

using namespace std;
using namespace my;

class Sellor
:public Thread 
{
public:
    Sellor(int &num, MutexLock &mutex, Condition &cond)
        :_num(num)
         ,_mutex(mutex)
         ,_cond(cond)
    {
        start();
    }
    void run()
    {
        //....do something
        int i = 0;
        while(i<10)
        {
            _mutex.lock();
            if(_num == 0)
            {
                _cond.wait();
                if(_num == 0)//在收到唤醒信号和lock的期间,num被其它线程减到0了
                {
                    _mutex.unlock();      
                    continue;
                }
            }
            _num--;
            cout << "sell:1" << endl;
            i++;
            _mutex.unlock(); 
        }
    }
private:
    int &_num;
    MutexLock &_mutex;
    Condition &_cond;
};

class Producer
:public Thread 
{
public:
    Producer(int &num, MutexLock &mutex, Condition &cond)
        :_num(num)
         ,_mutex(mutex)
         ,_cond(cond)
    {
        start();
    }
    void run()
    {
        //....do something
        int i = 0;
        while(i < 10)
        {
            _mutex.lock();
            _num++;
            i++;
            cout << "produce:1" << endl;
            _cond.notify();
            _mutex.unlock();
            usleep(0.5);
        }
    }
private:
    int &_num;
    MutexLock &_mutex;
    Condition &_cond;
};

void test()
{
    MutexLock mutex;
    Condition cond(mutex);
    int num = 10;
    Producer p(num, mutex, cond);
    Sellor s(num, mutex, cond);
    Producer p2(num, mutex, cond);
    Sellor s1(num, mutex, cond);
    Sellor s2(num, mutex, cond);
    p.join();
    s.join();
    p2.join();
    s1.join();
    s2.join();
    cout << num << endl;
}

int main()
{
    test();
    return 0;
}

 

 

更规范的写法是下面这种:

#ifndef __MY__CUSTOMER__H
#define __MY__CUSTOMER__H

#include "thread.hh"
#include "TaskQueue.hh"
#include <unistd.h>
#include <iostream>

using namespace std;

namespace my
{
class Customer
:public Thread 
{
public:
    Customer(TaskQueue & taskQue)
        :_taskQue(taskQue){}

private:
    void run()
    {
        //....do something
        int i = 0;
        while(i++ < 10)
        {
            int num = _taskQue.pop();
            cout << "Customer:" << num << endl;
        }
    }

    TaskQueue & _taskQue;
};
}

#endif

Prodeucer.hh

#ifndef __MY__PRODUCER__H
#define __MY__PRODUCER__H

#include "thread.hh"
#include "TaskQueue.hh"
#include <unistd.h>
#include <iostream>

using namespace std;

namespace my
{
class Producer
:public Thread 
{
public:
    Producer(TaskQueue & taskQue)
        :_taskQue(taskQue){}

private:
    void run()
    {
        //....do something
        ::srand(::clock());//调用C函数规范写法,函数名前加上::
        int i = 0;
        while(i++ < 10)
        {
            int  num = ::rand()%100;
            _taskQue.push(num);
            cout << "Producer:" << num << endl;
            usleep(0.5);
        }
    }

    TaskQueue & _taskQue;
};
}

#endif

test.cc 

#include "thread.hh"
#include "TaskQueue.hh"
#include "Customer.hh"
#include "Prodeucer.hh"
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <memory>

using namespace std;
using namespace my;


void test()
{
    TaskQueue taskQue(5);
    Producer p(taskQue);
    Customer s(taskQue);
    unique_ptr<Thread> p2(new Producer(taskQue));
    unique_ptr<Thread> s2(new Customer(taskQue));

    p.start();
    s.start();
    p2->start();
    s2->start();

    p.join();
    s.join();
    p2->join();
    s2->join();
}

int main()
{
    test();
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值