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

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

作者: 奈斯艾迪 | 来源:发表于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;
}

相关文章

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

    转载自:一个基于信号量的简易线程池 信号无需由同一个线程来获取和释放,因此信号可用于异步事件通知,如用于信号处理程...

  • Hystrix线程隔离技术解析-信号量

    hystrix的线程隔离技术除了线程池,还有另外一种方式:信号量。 线程池和信号量的区别 在《Hystrix线程隔...

  • Java其他类型的锁(三)

    一、Semaphore 信号量 Semaphore 是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞...

  • 2、ios下如何实现指定线程数目的线程池?

    ios下如何实现指定线程数目的线程池? 1、GCD的信号量机制(dispatch_semaphore) 信号量是一...

  • 线程池-1

    要点: 1.线程池原理,wait/notify ? 实现一个简易的线程池,http://ifeve.com/thr...

  • 简易线程池

    来自《Java并发编程的艺术》 一个简易的线程池的实现。三个类:ThreadPool线程池接口DefaultThr...

  • ThreadPoolExecutor的内部工作原理

    一、初始化一个线程池 基于ThreadPoolExecutor类初始化一个指定线程数的线程池线程池 二、提交任务 ...

  • 理解GCD

    (1)博客:深入理解GCD 理解iOS中的线程池 多线程理解 ?:(1)信号量--...

  • GCD的一些测试

    对GCD的封装 如何实现指定线程数目的线程池? 使用信号量 这样子创建的的线程最多也就是三个。因为信号量初始化的时...

  • Java基础知识(三):Hystrix信号量 VS线程池

    3. Hystrix信号量 VS线程池 信号量模式 接受请求和执行下游依赖在同一线程内完成,不存在线程上下文切换带...

网友评论

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

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