日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C/C++开发】C++实现简单的线程池

發布時間:2025/7/14 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C/C++开发】C++实现简单的线程池 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C++實現簡單的線程池

線程池編程簡介:

????在我們的服務端的程序中運用了大量關于池的概念,線程池、連接池、內存池、對象池等等。使用池的概念后可以高效利用服務器端的資源,比如沒有大量的線程在系統中進行上下文的切換,一個數據庫連接池,也只需要維護一定里的連接,而不是占用很多數據庫連接資源。同時它們也避免了一些耗時的操作,比如創建一個線程,申請一個數據庫連接,而且可能就只使用那么一次,然后就立刻釋放剛申請的資源,效率很低。

????在我的上一篇blog中已經實現一個線程基類了,在這里我們只需要實現一個線程池類ThreadPool和該線程池調度的工作線程類WorkThread即可,而且WorkThread是繼承自Thread類的。

?

實現思路:

????一個簡單的線程池的實現思路一般如下:

  • ThreadPool中創建多個線程(WorkThreadk對象),每個線程均處于阻塞狀態,等待任務的到來
  • ThreadPool提供一個提交任務的接口,如post_job(ProcCallback func, void* data); post_job后會立即返回,不會阻塞
  • ThreadPool維護一個空閑線程隊列,當客戶程序調用post_job()后,如果空閑隊列中有空閑線程,則取出一個線程句柄,并設置任務再給出新任務通知事件即可,處理等待的線程捕捉到事件信號后便開始執行任務,執行完后將該線程句柄重新push到空閑線程隊列中
  • 該線程池采用回調函數方式
  • 首先我們實現一個WorkThread類:

    ?1?typedef?void?(APR_THREAD_FUNC?*ProcCallBack)(void*);????????//回調函數指針
    ?2?//由線程池調度的工作線程
    ?3?class?WorkThread?:?public?Thread ? ? ?//Thread類的實現可參考我上一篇的blog: 《C++封裝一個簡單的線程類》
    ?4?{
    ?5?????friend?class?ThreadPool;
    ?6?public:
    ?7?????WorkThread(ThreadPool*?pthr_pool)
    ?8?????{
    ?9?????????thr_pool_????=?pthr_pool;
    10?????????cb_func_????=?NULL;
    11?????????param_????????=?NULL;
    12?????}
    13?????virtual?~WorkThread(){}
    14?????void????set_job(ProcCallBack?func,?void*?param)
    15?????{
    16?????????cb_func_????=?func;
    17?????????param_????????=?param;
    18?????????notify();????????????//通知有新的任務
    19?????}
    20?????//實現Thread的run方法,并調用用戶指定的函數
    21?????virtual?void?run()
    22?????{
    23?????????if?(cb_func_)
    24?????????????cb_func_(param_);
    25?????
    26?????????//reset?callback?function?pointer
    27?????????cb_func_????=?NULL;
    28?????????param_????????=?NULL;
    29?????
    30?????????//執行完任務,將該線程句柄移到線程池空閑隊列
    31?????????thr_pool_->move_to_idle_que(this);
    32?????}
    33?????
    34?private:
    35?????ThreadPool*????thr_pool_;????????//線程池指針
    36?????ProcCallBack????cb_func_;????????//回調函數地址
    37?????void*? ? ? ? ? ? ?param_; ? ? ? ? ??//回調函數參數
    38?};

    WorkThread中,有一個回調函數指針和參數,當有新任務時,會在run()中被調用,執行完后會將該線程移動到空閑線程隊列,等待下一次任務的提交。

    ThreadPool類定義如下:

    ?1?class?ThreadPool
    ?2?{
    ?3?????friend?class?WorkThread;
    ?4?public:
    ?5?????ThreadPool();
    ?6?????virtual?~ThreadPool();
    ?7?????int????start_thread_pool(size_t?thread_num?=?5);????????//啟動thread_num個線程
    ?8?????int????stop_thread_pool();??????????????????????????????????????//線束線程池
    ?9?????void????destroy();????????????????????????????????????????????????//銷毀線程池所申請的資源
    10?????void????post_job(ProcCallBack?func,?void*?data);????????//提交任務接口,傳入回調函數地址和參數
    11?
    12?protected:
    13?????WorkThread*????get_idle_thread();??????????????????????????????//從獲得空閑隊列中取得一個線程句柄
    14?????void????????append_idle_thread(WorkThread*?pthread);????//加入到thread_vec_和idl_que_中
    15?????void????????move_to_idle_que(WorkThread*?idlethread);????//將線程句柄加入到idle_que_中
    16?
    17?private:
    18?????size_t????????????????thr_num_;??????????????????????//線程數目
    19?????vector<WorkThread*>????????thr_vec_;????????//線程句柄集合
    20?????BlockQueue<WorkThread*>????idle_que_; ? ??//空閑線程隊列
    21?
    22?private:
    23?????//?not?implement
    24?????ThreadPool(const?ThreadPool&?);
    25?????ThreadPool&????operator=(const?ThreadPool&?);
    26?}; 線程池實現的關鍵是如何創建多個線程,并且當任務來臨時可以從線程池中取一個線程(也就是去得到其中一個線程的指針),然后提交任務并執行。還有一點就是當任務執行完后,應該將該線程句柄重新加入到空閑線程隊列,所以我們將ThreadPool的指針傳入給了WorkThread,thr_pool_最后可以調用move_to_idle_que(this)來將該線程句柄移到空閑隊列中。 ThreadPool中一些關鍵代碼的實現: ?1?int?ThreadPool::start_thread_pool(size_t?thread_num)
    ?2?{
    ?3?????assert(thread_num?!=?0);
    ?4?????thr_num_????=?thread_num;
    ?5?????int????ret????????=?0;
    ?6?????for?(size_t?i?=?0;?i?<?thr_num_;?++i)
    ?7?????{
    ?8?????????WorkThread*????pthr?=?new?WorkThread(this);
    ?9?????????pthr->set_thread_id(i);
    10?????????if?((ret?=?pthr->start())?!=?0)
    11?????????{
    12?????????????printf("start_thread_pool:?failed?when?create?a?work?thread:?%d\n",?i);
    13?????????????delete?pthr;
    14?????????????return?i;
    15?????????}
    16?????????append_idle_thread(pthr);????????
    17?????}
    18?????return?thr_num_;
    19?}
    20?int?ThreadPool::stop_thread_pool()
    21?{
    22?????for?(size_t?i?=?0;?i?<?thr_vec_.size();?++i)
    23?????{
    24?????????WorkThread*?pthr?=?thr_vec_[i];
    25?????????pthr->join();
    26?????????delete?pthr;
    27?????}
    28?????thr_vec_.clear();
    29?????idle_que_.clear();
    30?????return?0;
    31?}
    32?void?ThreadPool::destroy()
    33?{
    34?????stop_thread_pool();
    35?}
    36?void?ThreadPool::append_idle_thread(WorkThread*?pthread)
    37?{
    38?????thr_vec_.push_back(pthread);
    39?????idle_que_.push(pthread);
    40?}
    41?void?ThreadPool::move_to_idle_que(WorkThread*?idlethread)
    42?{
    43?????idle_que_.push(idlethread);
    44?}
    45?WorkThread*?ThreadPool::get_idle_thread()
    46?{
    47?????WorkThread*????pthr?=?NULL;
    48?????if?(!idle_que_.empty())
    49?????????pthr?=?idle_que_.take();
    50?????return?pthr;
    51?}
    52?void?ThreadPool::post_job(ProcCallBack?func,?void*?data)
    53?{
    54?????assert(func?!=?NULL);
    55?????WorkThread*?pthr?=?get_idle_thread();
    56?????while?(pthr?==?NULL)
    57?????{
    58?????????apr_sleep(500000);
    59?????????pthr?=?get_idle_thread();
    60?????}
    61?????pthr->set_job(func,?data);
    62?} ThreadPool中的BlockQueue<WorkThread*> 也就是一個線程安全的隊列,即對std::deque做了一個包裝,在插入和取出元素時加了一個讀寫鎖。


    使用示例: //任務執行函數,必須是ProcCallback類型 void count(void* param) { // do some your work, like:? int* pi = static_cast<int*>(param); int val = *pi + 1; printf("val=%d\n", val); pelete pi; } //程序中使用如下: ThreadPool* ptp = new ThreadPool(); ptp->start_thread_pool(3); //啟動3 個線程 ptp->post_job(count, new int(1)); //提交任務 ptp->post_job(count, new int(2)); ptp->post_job(count, new int(3)); //程序線束時 ptp->stop_thread_pool(); 其實count()函數就是我們的業務實現代碼,有任務時,可以提交給線程池去執行。 結尾: 其實實現一個線程池或其它什么池并不難,當然線程安全和效率還是要從多寫代碼的經驗中獲取。像這個線程池也就是基于預創多個建線程,保保存好它們的線程句柄,當有新任務時取一個線程執行即可,執行完后一定要歸還到空閑線程隊列中,當然我們可以在線程池中增加一個任務隊列,因為當post_job()時,若當時沒有空閑線程,有兩種方案,一是等待有空閑線程,二是加入到任務隊列,當WorkThread線程執行完一個任務后,從任務隊列中取一個任務繼續執行即可,不會阻塞在post_job()中。 另外,我們可以封裝一些線程安全的隊列和map什么的,這樣在程序中就不用擔心創建一個多線程共享的隊列時,還必須創建一個鎖,挺麻煩的,比如上面的BlockQueue<Type>直接拿來用就行了。

    轉載于:https://www.cnblogs.com/huty/p/8517387.html

    總結

    以上是生活随笔為你收集整理的【C/C++开发】C++实现简单的线程池的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。