zoukankan      html  css  js  c++  java
  • 简单的C++11线程池实现

    线程池的C++11简单实现,源代码来自Github上作者progschj,地址为:A simple C++11 Thread Pool implementation,具体博客可以参见Jakob’s Devlog,地址为:A Thread Pool with C++11

    1、线程池的实现代码如下:

    ThreadPool.h

    #ifndef THREAD_POOL_H
    #define THREAD_POOL_H
    
    #include <vector>
    #include <queue>
    #include <memory>
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    #include <future>
    #include <functional>
    #include <stdexcept>
    
    class ThreadPool {
    public:
     ThreadPool(size_t);
     template<class F, class... Args>
     auto enqueue(F&& f, Args&&... args) 
         -> std::future<typename std::result_of<F(Args...)>::type>;
     ~ThreadPool();
    private:
     // need to keep track of threads so we can join them
     std::vector< std::thread > workers;
     // the task queue
     std::queue< std::function<void()> > tasks;
     
     // synchronization
     std::mutex queue_mutex;
     std::condition_variable condition;
     bool stop;
    };
    
    // the constructor just launches some amount of workers
    inline ThreadPool::ThreadPool(size_t threads)
     :   stop(false)
    {
     for(size_t i = 0;i<threads;++i)
         workers.emplace_back(
             [this]
             {
                 for(;;)
                 {
                     std::function<void()> task;
    
                     {
                         std::unique_lock<std::mutex> lock(this->queue_mutex);
                         this->condition.wait(lock,
                             [this]{ return this->stop || !this->tasks.empty(); });
                         if(this->stop && this->tasks.empty())
                             return;
                         task = std::move(this->tasks.front());
                         this->tasks.pop();
                     }
    
                     task();
                 }
             }
         );
    }
    
    // add new work item to the pool
    template<class F, class... Args>
    auto ThreadPool::enqueue(F&& f, Args&&... args) 
     -> std::future<typename std::result_of<F(Args...)>::type>
    {
     using return_type = typename std::result_of<F(Args...)>::type;
    
     auto task = std::make_shared< std::packaged_task<return_type()> >(
             std::bind(std::forward<F>(f), std::forward<Args>(args)...)
         );
         
     std::future<return_type> res = task->get_future();
     {
         std::unique_lock<std::mutex> lock(queue_mutex);
    
         // don't allow enqueueing after stopping the pool
         if(stop)
             throw std::runtime_error("enqueue on stopped ThreadPool");
    
         tasks.emplace([task](){ (*task)(); });
     }
     condition.notify_one();
     return res;
    }
    
    // the destructor joins all threads
    inline ThreadPool::~ThreadPool()
    {
     {
         std::unique_lock<std::mutex> lock(queue_mutex);
         stop = true;
     }
     condition.notify_all();
     for(std::thread &worker: workers)
         worker.join();
    }
    
    #endif
    

    2、基本的用法:

    // create thread pool with 4 worker threads
    ThreadPool pool(4);
    
    // enqueue and store future
    auto result = pool.enqueue([](int answer) { return answer; }, 42);
    
    // get result from future
    std::cout << result.get() << std::endl;
    

    3、测试C++11线程池的例子程序如下:

    example.cpp

    #include <iostream>
    #include <vector>
    #include <chrono>
    
    #include "ThreadPool.h"
    
    int main()
    {
        
        ThreadPool pool(4);
        std::vector< std::future<int> > results;
    
        for(int i = 0; i < 8; ++i) {
            results.emplace_back(
                pool.enqueue([i] {
                    std::cout << "hello " << i << std::endl;
                    std::this_thread::sleep_for(std::chrono::seconds(1));
                    std::cout << "world " << i << std::endl;
                    return i*i;
                })
            );
        }
    
        for(auto && result: results)
            std::cout << result.get() << ' ';
        std::cout << std::endl;
        
        return 0;
    }
    

    编译运行example.cpp时需要添加C++11的支持,并且要加入pthread库的链接。
    在Linux下的编译的命令为: g++ example.cpp -o example -std=c++11 -lpthread;如果在VS2017中使用,由于默认支持C++11,可以直接创建一个控制台程序,添加ThreadPool.h和example.cpp到项目,编译运行即可。

    在Ubuntu18.10下测试如下:

    havealex@havealex:~/GithubProjects/ThreadPool$ ls
    COPYING  example.cpp  README.md  ThreadPool.h
    havealex@havealex:~/GithubProjects/ThreadPool$ g++ example.cpp -o example -std=c++11
    /usr/bin/ld: /tmp/ccduRGse.o: in function `std::thread::thread<ThreadPool::ThreadPool(unsigned long)::{lambda()#1}, , void>(ThreadPool::ThreadPool(unsigned long)::{lambda()#1}&&)':
    example.cpp:(.text._ZNSt6threadC2IZN10ThreadPoolC4EmEUlvE_JEvEEOT_DpOT0_[_ZNSt6threadC5IZN10ThreadPoolC4EmEUlvE_JEvEEOT_DpOT0_]+0x2f): undefined reference to `pthread_create'
    collect2: error: ld returned 1 exit status
    havealex@havealex:~/GithubProjects/ThreadPool$ g++ example.cpp -o example -std=c++11 -lpthread
    havealex@havealex:~/GithubProjects/ThreadPool$ ls
    > ^C
    havealex@havealex:~/GithubProjects/ThreadPool$ ls
    COPYING  example  example.cpp  README.md  ThreadPool.h
    havealex@havealex:~/GithubProjects/ThreadPool$ ./example 
    hello 0
    hello 1
    hello 2
    hello 3
    world 1
    hello 4
    world 0
    hello 5
    0 1 world 2
    hello 6
    4 world 3
    hello 7
    9 world 5
    world 4
    16 25 world 6
    36 world 7
    49 
    

    可以看出,结果的输出是无序并行的。

  • 相关阅读:
    游标和视图
    sql server 变量与集合运算
    sql server 流程控制
    sql server 基础查询和子查询
    数据库范式快速理解
    创建数据库与数据表
    SQL server 使用
    Android studio 下载依赖jar包慢
    java根据list数据通过接口姓名并填充
    【翻译】Promises/A+规范
  • 原文地址:https://www.cnblogs.com/ccf19881030/p/12004815.html
Copyright © 2011-2022 走看看