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