美文网首页
一个基于信号量的简易线程池

一个基于信号量的简易线程池

作者: 奈斯艾迪 | 来源:发表于2015-03-26 16:43 被阅读0次

    转载自:一个基于信号量的简易线程池


    信号无需由同一个线程来获取和释放,因此信号可用于异步事件通知,如用于信号处理程序中。同时,由于信号包含状态,因此可以异步方式使用,而不用象条件变量那样要求获取互斥锁。但是,信号的效率不如互斥锁高。缺省情况下,如果有多个线程正在等待信号,则解除阻塞的顺序是不确定的。信号在使用前必须先初始化,但是信号没有属性。计数信号量与互斥锁一起使用时的功能几乎与条件变量一样强大。在许多情况下,使用计数信号量实现的代码比使用条件变量实现的代码更为简单。本文参考:1、Linux多线程编程-信号量的使用2、Linux C++ 一个线程池的简单实现


    CThread.h

    #ifndef CTHREAD_H_
    #define CTHREAD_H_
    
    #include <pthread.h>
    
    class CThread {
    private:
        pthread_t m_thread; //保持线程句柄
    public:
        CThread(void* (*threadFuction)(void*),void* threadArgv);
        virtual ~CThread();
    
        void JoinThread();
    };
    
    #endif /* CTHREAD_H_ */
    

    CThread.cpp

    #include "CThread.h"
    
    CThread::CThread(void* (*threadFuction)(void*),void* threadArgv) {
    
        // 初始化线程属性
        pthread_attr_t threadAttr;
        pthread_attr_init(&threadAttr);
    
        pthread_create(&m_thread, &threadAttr, threadFuction, threadArgv);
    }
    
    CThread::~CThread() {
        // TODO Auto-generated destructor stub
    }
    
    
    void CThread::JoinThread()
    {
        // join
        pthread_join(m_thread, NULL);
    }
    

    CThreadManager.h

    #ifndef CTHREADMANAGER_H_
    #define CTHREADMANAGER_H_
    
    #include <stdio.h>
    #include <list>
    #include <queue>
    #include <semaphore.h>
    
    #include "CThread.h"
    
    using namespace std;
    
    class CThreadManager {
        friend void* ManageFuction(void*);
    private:
        sem_t m_sem;    // 信号量
        pthread_mutex_t m_mutex; // 互斥锁
    
        queue<int> m_queWork; // 工作队列
        list<CThread*> m_lstThread; // 线程list
    
        int (*m_threadFuction)(int); //函数指针,指向main函数传过来的线程执行函数
    
    
    public:
        CThreadManager(int (*threadFuction)(int), int nMaxThreadCnt);
        virtual ~CThreadManager();
    
        int WaitSem();
    
        int PostSem();
    
        int LockMutex();
    
        int UnlockMutex();
    
        void PushWorkQue(int nWork);
    
        int PopWorkQue();
    
        int RunThreadFunction(int nWork);
    };
    
    #endif /* CTHREADMANAGER_H_ */
    

    CThreadManager.cpp

    #include "CThreadManager.h"
    
    // 线程执行函数,它只是个壳子,处理信号量和互斥锁等,
    // 最后调用main函数传过来的线程执行函数来实现业务处理
    void* ManageFuction(void* argv)
    {
        CThreadManager* pManager = (CThreadManager*)argv;
    
        // 进行无限循环(意味着线程是不销毁的,重复利用)
        while(true)
        {
            // 线程开启后,就在这里阻塞着,直到main函数设置了信号量
            pManager->WaitSem();
            printf("thread wakeup.\n");
    
            // 从工作队列中取出要处理的数
            pManager->LockMutex();
            int nWork = pManager->PopWorkQue();
            pManager->UnlockMutex();
    
            printf("call Count function.\n");
            pManager->RunThreadFunction(nWork);
        }
    
        return 0;
    }
    
    
    CThreadManager::CThreadManager(int (*threadFuction)(int), int nMaxThreadCnt) {
    
        sem_init(&m_sem, 0, 0);
        pthread_mutex_init(&m_mutex, NULL);
    
        m_threadFuction = threadFuction;
    
        for(int i=0; i<nMaxThreadCnt; i++)
        {
            CThread* pThread = new CThread(ManageFuction, this);
            printf("thread started.\n");
            m_lstThread.push_back(pThread);
        }
    }
    
    CThreadManager::~CThreadManager()
    {
        sem_destroy(&m_sem);
        pthread_mutex_destroy(&m_mutex);
    
        list<CThread*>::iterator it;
        for(it=m_lstThread.begin(); it!=m_lstThread.end();it++)
        {
            (*it)->JoinThread();
        }
    }
    
    // 等待信号量
    int CThreadManager::WaitSem()
    {
        return sem_wait(&m_sem);
    }
    
    // 设置信号量
    int CThreadManager::PostSem()
    {
        return sem_post(&m_sem);
    }
    
    // 取得锁
    int CThreadManager::LockMutex()
    {
        int n= pthread_mutex_lock(&m_mutex);
        return n;
    }
    
    // 释放锁
    int CThreadManager::UnlockMutex()
    {
        return pthread_mutex_unlock(&m_mutex);
    }
    
    // 往工作队列里放要处理的数
    void CThreadManager::PushWorkQue(int nWork)
    {
        m_queWork.push(nWork);
    }
    
    // 从工作队列中取出要处理的数
    int CThreadManager::PopWorkQue()
    {
        int nWork = m_queWork.front();
        m_queWork.pop();
    
        return nWork;
    }
    
    // 执行main函数传过来的线程执行函数
    int CThreadManager::RunThreadFunction(int nWork)
    {
        return (*m_threadFuction)(nWork);
    }
    

    ThreadTest.cpp

    #include <stdio.h>
    #include <unistd.h>
    
    #include "CThreadManager.h"
    
    using namespace std;
    
    // 线程要执行的函数
    int Count(int nWork)
    {
        int nResult = nWork * nWork;
        printf("count result is %d\n",nResult);
    
        return 0;
    }
    
    int main() {
    
        // 创建线程管理类的实例,把要执行的线程函数和最大线程数传进去
        CThreadManager* pManager = new CThreadManager(Count, 3);
    
        // 把要进行计算的数放到工作队列中
        pManager->PushWorkQue(5);
        pManager->PushWorkQue(20);
    
        // 设置信号量,唤醒线程
        pManager->PostSem();
        pManager->PostSem();
    
        // 等待子线程执行
        sleep(1);
    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:一个基于信号量的简易线程池

          本文链接:https://www.haomeiwen.com/subject/kbxnxttx.html