zoukankan      html  css  js  c++  java
  • 使用C++STL的并发接口完成线程池

      最近两天看了以下《The C++ Standard library》里介绍的并发模型。今天搞了一下午,排查了bug,终于搞定了:

      总体来讲还是比pthread提供的接口要简洁。

      定义task

    class task
    {
    public:
        virtual void execute()=0;
    };

      threadpool.h

    #ifndef MATHREADPOOL_H
    #define MATHREADPOOL_H
    #include <queue>
    #include "common.h"
    #include <vector>
    #include <condition_variable>
    #include <mutex>
    #include <future>
    #include <memory>
    
    namespace manch1n
    {
    using taskSPtr = std::shared_ptr<manch1n::task>;
    class mathreadpool : uncopyable
    {
    public:
        using lockGuard = std::lock_guard<std::mutex>;
        using uniqueLock = std::unique_lock<std::mutex>;
    
        explicit mathreadpool(size_t nthreads = 4);
        void initAndRun();
        void pushTask(taskSPtr &);
        bool isEmpty();
    
    private:
        static void *routine(void *arg);
    
        taskSPtr popTask();
        std::vector<std::thread::id> _threads;
        std::queue<taskSPtr> _tasks;
        size_t _nthreads;
        std::mutex _mutex;
        std::condition_variable _condition;
    };
    
    } // namespace manch1n
    
    #endif //MATHREADPOOL_H

      threadpool.cc

    #include "mathreadpool.h"
    
    namespace manch1n
    {
    mathreadpool::mathreadpool(size_t nthreads) : _nthreads(nthreads)
    {
    }
    
    void mathreadpool::initAndRun()
    {
        for (int i = 0; i < _nthreads; ++i)
        {
            std::thread t(routine, this);
            t.detach();
            _threads.push_back(t.get_id());
        }
    }
    
    void *mathreadpool::routine(void *arg)
    {
        mathreadpool &pool = *static_cast<mathreadpool *>(arg);
        while (1)
        {
            taskSPtr ptask = pool.popTask();
            ptask->execute();
        }
        return NULL;
    }
    
    void mathreadpool::pushTask(taskSPtr &t)
    {
        {
            lockGuard lock(_mutex);
            _tasks.push(t);
        }
        _condition.notify_one();
    }
    
    taskSPtr mathreadpool::popTask()
    {
        uniqueLock lock(_mutex);
        _condition.wait(lock,[this](){return !this->isEmpty();});
        taskSPtr p(_tasks.front());
        _tasks.pop();
        return p;
    }
    
    bool mathreadpool::isEmpty()
    {
        return _tasks.empty();
    }
    
    } // namespace manch1n

      测试一下:

      

    #include <iostream>
    #include <iomanip>
    #include <unistd.h>
    #include "mathreadpool.h"
    using namespace std;
    using namespace manch1n;
    
    class drive1:public manch1n::task
    {
    public:
        virtual void execute() override
        {
            cout<<s<<endl;
        }
        string s="drive1";
    };
    
    class drive2:public manch1n::task
    {
    public:
        virtual void execute() override
        {
            cout<<s<<endl;
        }
        string s="drive2";
    };
    
    int main(int argc, char **argv)
    {
        taskSPtr d1=make_shared<drive1>();
        taskSPtr d2=make_shared<drive2>();
        mathreadpool pool(4);
        pool.initAndRun();
        pool.pushTask(d1);
        pool.pushTask(d2);
        ::pause();
        return 0;
    }

      输出:

    [manch1n@centos7 build]$ ./benchmark 
    drive2
    drive1
    ^C
    [manch1n@centos7 build]$ ./benchmark 
    drive1
    drive2
    ^C
    [manch1n@centos7 build]$ ./benchmark 
    drive1
    drive2
  • 相关阅读:
    Java 中位移运算符 >>,>>>,<<
    HashMap 源码解读
    CentOS 配置防火墙操作实例(启、停、开、闭端口)
    CentOS 配置防火墙操作实例(启、停、开、闭端口)
    js实现页面重新加载
    js实现页面重新加载
    关于Ajax的技术组成与核心原理
    关于Ajax的技术组成与核心原理
    PHP水印制作
    PHP水印制作
  • 原文地址:https://www.cnblogs.com/manch1n/p/11773136.html
Copyright © 2011-2022 走看看