利用muduo原线程池修改的可调度线程池源码

由于muduo的线程池是抢占式的,在锁过多利用的情况下我们需要自己利用自己的规则去分配和调度线程,我这个实现的就是一个可自己分配和调度的线程池,其特点有以下几点
1、每个线程都有自己的消息队列并且大小不限
2、每个线程都可自由阻塞,但是消息队列正常接受消息
3、可利用Run进行开启线程或者启动的时候利用一个列表开启线程池,很方便

/* 
 * File:   NonPreemptiveThreadPool.h
 * Author: zerber
 *
 * Created on 2017年9月1日, 下午1:27
 */
#pragma once

#include "local_common/Public.h"

#include <muduo/base/Thread.h>
#include <muduo/base/Mutex.h>
#include <muduo/base/Condition.h>
#include <muduo/base/CountDownLatch.h>

#ifndef NONPREEMPTIVETHREADPOOL_H
#define NONPREEMPTIVETHREADPOOL_H

typedef boost::function<void ()> Task;

struct RunThreadNode
{
    RunThreadNode(const std::string& name,int queuesize = 0):
    countDownLatch_(1),
    listMutex_(),
    blockMutex_(),
    notEmpty_(listMutex_),
    blockCond_(blockMutex_),
    isBolck_(false),
    threadName_(name),
    thread_(boost::bind(&RunThreadNode::RunInThread_,this),threadName_),
    running_(false),
    queuesize_(queuesize){}
    ~RunThreadNode()
    {
        if(running_)
        {
            ThreadStop();
        }
    }

    void PushTaskInQueue(const Task& task);
    void ThreadStart();
    void ThreadStop();
    const std::string& GetThreadName();
    void ThreadBlock();
    void ThreadWakeUp();

    muduo::CountDownLatch countDownLatch_;
private:
    Task Take_();
    void RunInThread_();

    muduo::MutexLock listMutex_;
    muduo::MutexLock blockMutex_;
    muduo::Condition notEmpty_;
    muduo::Condition blockCond_;
    bool isBolck_;
    std::string threadName_;

    muduo::Thread thread_;
    std::queue<Task> queue_;

    bool running_;
    int queuesize_;
};

typedef boost::shared_ptr<RunThreadNode> RunThreadNodePtr;

class NonPreemptiveThreadPool
{
public:
    //指定队列长度,指定生成哪些线程
    NonPreemptiveThreadPool(int queuesize,
            const std::string& name,
            int* threadList,
            int threadListNum);
    ~NonPreemptiveThreadPool();  

    void Run(int threadNum, const Task& f);
    void Stop(int threadNum);
    void AllStart();
    void AllStop();
    void ThreadBlock(int threadNum);
    void ThreadWakeUp(int threadNum);
private:

    boost::unordered_map<int, RunThreadNodePtr> threads_;
    int queuesize_;
    std::string name_;
};

#endif /* NONPREEMPTIVETHREADPOOL_H */
/* 
 * File:   NonPreemptiveThreadPool.cpp
 * Author: zerber
 *
 * Created on 2017年9月1日, 下午1:27
 */
#include "NonPreemptiveThreadPool.h"

#include <muduo/base/Exception.h>

void RunThreadNode::PushTaskInQueue(const Task& task)
{
    muduo::MutexLockGuard lock(listMutex_);

    queue_.push(task);
    notEmpty_.notify();
}

void RunThreadNode::ThreadStart()
{
    running_ = true;
    thread_.start();
}

void RunThreadNode::ThreadStop()
{
    {
        muduo::MutexLockGuard lock(listMutex_);
        running_ = false;
        notEmpty_.notify();
    }
    thread_.join();

    LOG_DEBUG << "thread " << threadName_ << " stop";
}

const std::string& RunThreadNode::GetThreadName()
{
    return threadName_;
}

void RunThreadNode::ThreadBlock()
{
    isBolck_ = true;
}

void RunThreadNode::ThreadWakeUp()
{
    if(isBolck_)
    {
        isBolck_ = false;
        blockCond_.notify();
    }
}

Task RunThreadNode::Take_()
{
    muduo::MutexLockGuard lock(listMutex_);
    while(queue_.empty() && running_)
    {
        notEmpty_.wait();
    }

    Task task;
    if(!queue_.empty())
    {
        task = queue_.front();
        queue_.pop();
    }
    return task;
}

void RunThreadNode::RunInThread_()
{
    muduo::MutexLockGuard lock(blockMutex_);
    try
    {
        while (running_)
        {
          Task task(Take_());
          while(isBolck_)
          {
              blockCond_.wait();
          }

          if(task)
          {
            task();
          }
        }
    }
    catch (const muduo::Exception& ex)
    {
      fprintf(stderr, "exception caught in ThreadPool %s\n", threadName_.c_str());
      fprintf(stderr, "reason: %s\n", ex.what());
      fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
      abort();
    }
    catch (const std::exception& ex)
    {
      fprintf(stderr, "exception caught in ThreadPool %s\n", threadName_.c_str());
      fprintf(stderr, "reason: %s\n", ex.what());
      abort();
    }
    catch (...)
    {
      fprintf(stderr, "unknown exception caught in ThreadPool %s\n", threadName_.c_str());
      throw;
    }
}
////////////////////////////////////////////////////////////////////////////////

NonPreemptiveThreadPool::NonPreemptiveThreadPool(int queuesize, 
                                                 const std::string& name,
                                                 int* threadList = NULL, 
                                                 int threadListNum = 0)
:queuesize_(queuesize),
name_(name)        
{
    if(threadList != NULL && threadListNum > 0)
    {
        for(int i=0 ; i<threadListNum ; i++)
        {
            char id[32];
            snprintf(id, sizeof(id), "%d", threadList[i]);
            RunThreadNodePtr pCurRunThreadNode = boost::make_shared<RunThreadNode>(name_+id,queuesize_);
            threads_.insert(make_pair(threadList[i],pCurRunThreadNode));
        }
    }
}

NonPreemptiveThreadPool::~NonPreemptiveThreadPool()
{
    AllStop();
}

void NonPreemptiveThreadPool::Run(int threadNum, const Task& f)
{
    auto iter = threads_.find(threadNum);
    if(iter != threads_.end())
    {
        iter->second->PushTaskInQueue(f);
    }
    else
    {
        char id[32];
        snprintf(id, sizeof(id), "%d", threadNum);
        RunThreadNodePtr pCurRunThreadNode = boost::make_shared<RunThreadNode>(name_+id,queuesize_);
        threads_.insert(make_pair(threadNum,pCurRunThreadNode));
        pCurRunThreadNode->ThreadStart();
        LOG_DEBUG << "thread " << pCurRunThreadNode->GetThreadName() << " start";
    }
}

void NonPreemptiveThreadPool::Stop(int threadNum)
{
    auto iter = threads_.find(threadNum);
    if(iter == threads_.end()) return;

    iter->second->ThreadStop();
    LOG_DEBUG << "thread " << iter->second->GetThreadName() << " stop";
}

void NonPreemptiveThreadPool::AllStart()
{
    auto iter = threads_.begin();
    for(; iter!=threads_.end() ;iter++)
    {
        iter->second->ThreadStart();
    }
    LOG_DEBUG << "all threads has been start";
}

void NonPreemptiveThreadPool::AllStop()
{
    auto iter = threads_.begin();
    for(; iter!=threads_.end() ;iter++)
    {
        iter->second->ThreadStop();
    }
    LOG_DEBUG << "all threads has been stop";
}

void NonPreemptiveThreadPool::ThreadBlock(int threadNum)
{
    auto iter = threads_.find(threadNum);
    if(iter == threads_.end()) return;
    iter->second->ThreadBlock();
    LOG_DEBUG << "thread " << iter->second->GetThreadName() << " block";
}

void NonPreemptiveThreadPool::ThreadWakeUp(int threadNum)
{
    auto iter = threads_.find(threadNum);
    if(iter == threads_.end()) return;
    iter->second->ThreadWakeUp();
    LOG_DEBUG << "thread " << iter->second->GetThreadName() << " wake up";
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值