【C/C++开发】C++实现简单的线程池
生活随笔
收集整理的這篇文章主要介紹了
【C/C++开发】C++实现简单的线程池
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C++實現簡單的線程池
線程池編程簡介:
????在我們的服務端的程序中運用了大量關于池的概念,線程池、連接池、內存池、對象池等等。使用池的概念后可以高效利用服務器端的資源,比如沒有大量的線程在系統中進行上下文的切換,一個數據庫連接池,也只需要維護一定里的連接,而不是占用很多數據庫連接資源。同時它們也避免了一些耗時的操作,比如創建一個線程,申請一個數據庫連接,而且可能就只使用那么一次,然后就立刻釋放剛申請的資源,效率很低。
????在我的上一篇blog中已經實現一個線程基類了,在這里我們只需要實現一個線程池類ThreadPool和該線程池調度的工作線程類WorkThread即可,而且WorkThread是繼承自Thread類的。
?
實現思路:
????一個簡單的線程池的實現思路一般如下:
首先我們實現一個WorkThread類:
?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做了一個包裝,在插入和取出元素時加了一個讀寫鎖。
轉載于:https://www.cnblogs.com/huty/p/8517387.html
總結
以上是生活随笔為你收集整理的【C/C++开发】C++实现简单的线程池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hash集合方法使用
- 下一篇: postman api