初識(shí)c++多線程

主要參考以下兩篇博客
c++多線程 thread類
c++實(shí)現(xiàn)線程池
當(dāng)一個(gè)thread被創(chuàng)建以后要么join等待線程執(zhí)行完畢,要么detached將線程獨(dú)立出去
線程池適合的幾個(gè)場(chǎng)景
(1) 單位時(shí)間內(nèi)處理任務(wù)頻繁而且任務(wù)處理時(shí)間短;
(2) 對(duì)實(shí)時(shí)性要求較高。如果接受到任務(wù)后在創(chuàng)建線程,可能滿足不了實(shí)時(shí)要求,因此必須采用線程池進(jìn)行預(yù)創(chuàng)建。

#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);                          //構(gòu)造函數(shù)
    template<class F, class... Args>             //類模板
    auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>;//任務(wù)入隊(duì)
    ~ThreadPool();                              //析構(gòu)函數(shù)
 
private:
    std::vector< std::thread > workers;            //線程隊(duì)列,每個(gè)元素為一個(gè)Thread對(duì)象
    std::queue< std::function<void()> > tasks;     //任務(wù)隊(duì)列,每個(gè)元素為一個(gè)函數(shù)對(duì)象    
 
    std::mutex queue_mutex;                        //互斥量
    std::condition_variable condition;             //條件變量
    bool stop;                                     //停止
};
 
// 構(gòu)造函數(shù),把線程插入線程隊(duì)列,插入時(shí)調(diào)用embrace_back(),用匿名函數(shù)lambda初始化Thread對(duì)象
inline ThreadPool::ThreadPool(size_t threads) : stop(false){
 
    for(size_t i = 0; i<threads; ++i)
        workers.emplace_back(
            [this]
            {
                for(;;)
                {
                    // task是一個(gè)函數(shù)類型,從任務(wù)隊(duì)列接收任務(wù)
                    std::function<void()> task;  
                    {
                        //給互斥量加鎖,鎖對(duì)象生命周期結(jié)束后自動(dòng)解鎖
                        std::unique_lock<std::mutex> lock(this->queue_mutex);
                        
                        //(1)當(dāng)匿名函數(shù)返回false時(shí)才阻塞線程,阻塞時(shí)自動(dòng)釋放鎖。
                        //(2)當(dāng)匿名函數(shù)返回true且受到通知時(shí)解阻塞,然后加鎖。
                        this->condition.wait(lock,[this]{ return this->stop || !this->tasks.empty(); });
                       
                         if(this->stop && this->tasks.empty())
                            return;
                        
                        //從任務(wù)隊(duì)列取出一個(gè)任務(wù)
                        task = std::move(this->tasks.front());
                        this->tasks.pop();
                    }                            // 自動(dòng)解鎖
                    task();                      // 執(zhí)行這個(gè)任務(wù)
                }
            }
        );
}
 
// 添加新的任務(wù)到任務(wù)隊(duì)列
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) 
    -> std::future<typename std::result_of<F(Args...)>::type>
{
    // 獲取函數(shù)返回值類型        
    using return_type = typename std::result_of<F(Args...)>::type;
 
    // 創(chuàng)建一個(gè)指向任務(wù)的只能指針
    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);  //加鎖
        if(stop)
            throw std::runtime_error("enqueue on stopped ThreadPool");
 
        tasks.emplace([task](){ (*task)(); });          //把任務(wù)加入隊(duì)列
    }                                                   //自動(dòng)解鎖
    condition.notify_one();                             //通知條件變量,喚醒一個(gè)線程
    return res;
}
 
// 析構(gòu)函數(shù),刪除所有線程
inline ThreadPool::~ThreadPool()
{
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        stop = true;
    }
    condition.notify_all();
    for(std::thread &worker: workers)
        worker.join();
}
 
#endif

一般來說要給線程設(shè)置一個(gè)標(biāo)志位,當(dāng)滿足條件后,跳出程序,等待線程池內(nèi)的所有線程執(zhí)行完畢后,執(zhí)行join

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來是分開三篇的,后來想想還是整...
    coder_pig閱讀 1,772評(píng)論 2 17
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,107評(píng)論 1 18
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽(yáng)閱讀 2,596評(píng)論 1 15
  • 線程 操作系統(tǒng)線程理論 線程概念的引入背景 進(jìn)程 之前我們已經(jīng)了解了操作系統(tǒng)中進(jìn)程的概念,程序并不能單獨(dú)運(yùn)行,只有...
    go以恒閱讀 1,793評(píng)論 0 6
  • 林炳文Evankaka原創(chuàng)作品。轉(zhuǎn)載自http://blog.csdn.net/evankaka 本文主要講了ja...
    ccq_inori閱讀 733評(píng)論 0 4

友情鏈接更多精彩內(nèi)容