前端時間偶然在github上看到了乙個非常精煉的
c++11執行緒池實現。作者用不到100行的**實現了乙個簡單的執行緒池,且使用了較多c++11的新特性。於是便想著自己也來動手看看,思路上基本是借鑑原版,但會加入一些自己的想法和嘗試,同時先避免對複雜語法的運用以理解執行緒池為首要目的。由於個人能力有限,如果**中有明顯bug歡迎指正,一起交流進步。
在貼原始碼之前先介紹一下執行緒池的基本組成,執行緒池一般由兩種角色構成:多個工作執行緒和乙個阻塞佇列。
一張便可以很直觀的展示執行緒池:
// task排隊應該先進先出,所以用佇列
std::mutex task_mutex;};
#endif
threadpool.cc:
#include
#include
"threadpool.h"
using
namespace std;
threadpool::
threadpool
(size_t num)
:stop
(false
)void threadpool::
entry()
);// 如果是執行緒池停止,則退出子執行緒
if(stop)
return
;// 否則就從任務佇列中取最靠前的乙個任務進行執行,並將任務出隊
task cur_task = std::
move
(tasks.
front()
);tasks.
pop();
lock.
unlock()
;// task取出後就可以解鎖
cur_task()
;}}threadpool::
~threadpool()
void threadpool::
shutdown()
cond.
notify_all()
;// 同時等待子執行緒執行完成
for(
auto
&th: threads)
th.join()
;}
測試**
main.cc:
#include #include #include "threadpool.h"
using namespace std;
int main()
) );
}for(auto && result: results)
std::cout << result.get() << ' ';
// .get()會阻塞直到獲取到結果,如果shutdown放到get之前則get會一直阻塞
pool.shutdown();
std::cout << std::endl;
return 0;
}
其中的一些關鍵點分析:
基本工作流程:執行緒池建構函式時建立n個執行緒,此時任務隊列為空,所以這些執行緒都在阻塞狀態,等到往任務佇列中新增task,工作執行緒則取走task並執行。
執行緒池的退出由使用者控制,提供了stop介面供使用者停止,停止執行緒時會等待正在執行task的工作執行緒執行完成再**。
**的主要實現就是entry()和add_task(),前者實現了等待取task的邏輯,後者實現了非同步執行task且支援各種型別的函式形式。其中關於add_task(),如注釋所說相當於是對乙個通用函式包裝器的改造,不同點在於通用包裝器的返回值可以return,而這裡新增的task還未被執行需要等到將來工作執行緒來取。
注意std::future是不能拷貝的,所以如果要放到vector中必須原地構造
先來看一下通用函式包裝器的實現:
或者換一種實現方式,雖然就包裝器來說多此一舉但是對於向add_task的轉化就更直觀:
針對以上**做基礎修改:
[1] a ****** c++ 11 thread pool implementation
[2] 《深入應用c++ 11》by 祈宇
基於C 11實現的執行緒池
最近在整理之前寫的一些東西,方便以後檢視 實現的主要原理是 乙個同步佇列,外部往同步佇列裡新增任務,然後喚醒執行緒有任務需要處理,執行緒取出任務即可。同步佇列 syncquene.hpp include include include templateclass syncquene bool ful...
C 11 執行緒池實現
c 11中已經新增了跨平台的thread相關工具,在一些輕量級使用場景中,使用std thread無疑會給我們帶來很多方便。這裡使用它實現了乙個簡單的執行緒池 easythreadpool.h ifndef easy thread pool h define easy thread pool h i...
C 11執行緒池的實現
執行緒池是指定執行緒建立的個數,每個執行緒只是建立銷毀一次。比起毫無限制的建立執行緒銷毀執行緒效率更高。畢竟頻繁的建立銷毀執行緒會消耗系統資源,而且系統建立執行緒也是有上限的。class thread pool thread pool thread pool int n done false els...