c/c++线程--3线程池

19 篇文章 0 订阅
3 篇文章 0 订阅

c/c++线程--3

最近一段时间在看linux下c语言的多线程,其中一个比较重要的应用就是线程池。自己也参照着网上的资料写了一个简单的线程池。这里做以总结。


1.解决问题,应用场景

我们的应用在任何时候都要准备应对数目巨大的连接请求,同时,这些请求所要完成的任务却又可能非常的简单,即只占用很少的处理时间。

总之线程池通常适合下面的几个场合:
  (1) 单位时间内处理任务频繁而且任务处理时间短
  (2) 对实时性要求较高。如果接受到任务后在创建线程,可能满足不了实时要求,因此必须采用线程池进行预创建。
  (3) 必须经常面对高突发性事件,比如Web服务器,如果有足球转播,则服务器将产生巨大的冲击。此时如果采取传统方法,则必须不停的大量产生线程,销毁线程。此时采用动态线程池可以避免这种情况的发生。

目的很明确,为了减少创建销毁带来的开销,尤其是当线程的任务简单的时候。

2. 设计思路

一般来说,线程池都是 采用预创建的技术,在应用启动之初便预先创建一定数目的线程。
应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务。

任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。如果线程池中预先分配的线程已经全部分配完毕,但此时又有新的任务请求,则线程池会动态的创建新的线程去适应这个请求。

当然,有可能,某些时段应用并不需要执行很多的任务,导致了线程池中的线程大多处于空闲的状态,为了节省系统资源,线程池就需要动态的销毁其中的一部分空闲线程。

因此,线程池都需要一个管理者,按照一定的要求去动态的维护其中线程的数目。

3. 核心模型


创建的线程都要从这里开始执行。


threadRoutine()
{
    while(1)
    {
        lock();
        while(0 == queueSize && notShutDown)	/// 如果没有任务,在这里等待
        {
            wait();
        }


        if(!notShutDown)		/// 在这里结束任务。
        {
            exit();
        }


        if(queueSize > 0)
        {
            mission = queue.pop();
            unlock();
            runMission();
        }
        else
        {
            unlock();
        }
    }
}


4. 简单线程池代码

头文件
/**
purpose :   基本线程池
            实现缓冲外部高并发任务数

author : oslo wang

data :  2015 05 19

next Version :  这里没有实现对线程池里线程的动态管理。
                如果空闲线程多,则销毁一些。
                如果等待的任务多,则创建一些线程。

*/
#include <pthread.h>
#include <queue>

/// 采用c++ stl中的队列来管理任务。
using std::queue;

/// 线程任务结构体
typedef struct st_threadMission
{
    void *(*process) (void *arg);
    void *  arg;
} threadMission;

threadMission * createThreadMission(void* (*process) (void *), void *arg);

/// 简单线程池类
class CThreadPool
{
public:
    CThreadPool(int maxThread = 10);
    ~CThreadPool();
    bool InitPool(int maxThread = 10);
    bool DestrPool();
    void addMission(threadMission * mission);
    //void * threadRoutine(void *arg);
    static void * threadRoutine(void *arg);

private:
    pthread_mutex_t     mutex;          /// 和条件变量一起使用的互斥锁
    pthread_cond_t      hasMission;     /// 条件变量,用于通知有任务处理。

    queue<threadMission*>    missionQueue;
    pthread_t*           threadId;
    unsigned int        maxThreadInPool;

    bool    isShutDown;
};

//void * threadRoutine(void *arg);
int ThreadPool_Test();

实现
#include "ThreadPool.h"
#include <stdio.h>
#include <unistd.h>


CThreadPool::CThreadPool(int maxThread)
{
    InitPool(maxThread);
}

CThreadPool::~CThreadPool()
{
    DestrPool();
}

bool CThreadPool::InitPool(int maxThread)
{
    printf("\nInitial Thread Pool.\n\n");
    if(maxThread <= 0)
        maxThread = 10;
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&hasMission, NULL);

    isShutDown = false;

    maxThreadInPool = maxThread;
    threadId = new pthread_t[maxThreadInPool];

    unsigned int i;
    for(i = 0; i < maxThreadInPool; ++i)
    {
        if(0 != pthread_create(&threadId[i], NULL, threadRoutine, this))
        {
            printf("error in CThreadPool::InitPool(), i = %d.\n", i);
        }
    }

    return true;
}

bool CThreadPool::DestrPool()
{
    if(isShutDown)
        return true;

    printf("\nDestroy Thread Pool.\n\n");
    isShutDown = true;
    pthread_cond_broadcast(&hasMission);


    int i;
    for(i = 0; i < maxThreadInPool; ++i)
    {
        pthread_join(threadId[i], NULL);
    }
    delete[]    threadId;
    threadId = NULL;

    threadMission *ptr = NULL;
    int queueNum = missionQueue.size();

    for(i = 0; i < queueNum; ++i)
    {
        ptr = missionQueue.front();
        missionQueue.pop();

        delete ptr;
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&hasMission);

    return true;
}

void CThreadPool::addMission(threadMission * mission)
{
    pthread_mutex_lock(&mutex);

    missionQueue.push(mission);

    pthread_mutex_unlock(&mutex);

    pthread_cond_signal(&hasMission);
}

void * CThreadPool::threadRoutine(void *arg)
{
    pthread_t tid = pthread_self();
    printf ("starting thread 0x%lu\n", tid);
    CThreadPool *ptr = (CThreadPool *)arg;
    while(1)
    {
        pthread_mutex_lock(&ptr->mutex);
        while(0 == ptr->missionQueue.size() && !ptr->isShutDown)
        {
            printf("thread 0x%lu is waiting.\n", tid);
            pthread_cond_wait(&ptr->hasMission, &ptr->mutex);
        }

        /**线程在这里销毁*/
        if(ptr->isShutDown)
        {
            pthread_mutex_unlock(&ptr->mutex);
            printf("thread 0x%lu will exit.\n", tid);
            pthread_exit(NULL);
        }

        threadMission * mission = NULL;
        if(ptr->missionQueue.size() > 0)
        {
            mission = ptr->missionQueue.front();
            ptr->missionQueue.pop();
            pthread_mutex_unlock(&ptr->mutex);

            void* (*process) (void *arg) = mission->process;
            void * arg = mission->arg;
            process(arg);
            delete mission;
            mission = NULL;

        }
        else
        {
            pthread_mutex_unlock(&ptr->mutex);
        }
    }
    pthread_exit(NULL);

    return NULL;
}

char argString[5][256] = { "Hello World.",
                    "Can you do this?",
                    "Holy shit!",
                    "rampage!",
                    "Could you play DOTA?"
                                    };

void * myprocess(void *arg)
{
    char *str = (char*)arg;
    printf("\nthread %lu\n", pthread_self());
    printf("#######arg : %s\n\n", str);
    sleep(1);

    return NULL;
}

threadMission * createThreadMission(void* (*process) (void *), void *arg)
{
    threadMission * tmp = new threadMission;
    tmp->process = process;
    tmp->arg = arg;

    return tmp;
}

int ThreadPool_Test()
{
    CThreadPool cp1(7);

    int i;
    threadMission *mission = NULL;
    for(i = 0; i < 5; ++i)
    {
        mission = createThreadMission(myprocess, argString[i]);
        cp1.addMission(mission);
    }

    sleep(10);

    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值